当前位置: 首页 > news >正文

深入理解C++中的list容器:介绍、使用与实现

目录

前言

1. list的基本介绍

2. list的基本使用

2.1 构造函数

2.2 迭代器使用

2.3 容量操作

2.4 元素访问

2.5 修改操作

2.6 迭代器失效问题

3. list的模拟实现

3.1 节点结构

3.2 迭代器实现

3.3 反向迭代器

4. list与vector的对比

总结


前言

在C++标准模板库(STL)中,list是一个非常重要的序列式容器,它基于双向链表实现,提供了高效的插入和删除操作。本文将全面介绍list的特性、使用方法、内部实现原理,以及与vector容器的对比,帮助开发者更好地理解和应用这一数据结构。


1. list的基本介绍

list是C++标准库中的一个序列容器,具有以下核心特性:

1. 双向链表结构:list底层采用双向链表实现,每个元素存储在独立的节点中,通过指针连接前后元素
2. 高效插入删除:在任意位置插入和删除元素的时间复杂度都是O(1)
3. 双向迭代:支持从前向后和从后向前的双向遍历
4. 不支持随机访问:访问特定位置的元素需要线性时间O(n)

与forward_list(单向链表)相比,list提供了更全面的功能,但相应地会占用更多内存空间。

2. list的基本使用

2.1 构造函数

list提供了多种构造函数:


 

list<int> l1;          // 空list
list<int> l2(5, 10);   // 5个元素,每个初始化为10
list<int> l3(l2);      // 拷贝构造
list<int> l4(arr, arr + sizeof(arr)/sizeof(arr[0])); // 范围构造


 

2.2 迭代器使用

list支持双向迭代器,包括正向和反向迭代器:

 

list<int> myList = {1, 2, 3, 4, 5};// 正向遍历
for(auto it = myList.begin(); it != myList.end(); ++it) {cout << *it << " ";
}// 反向遍历
for(auto rit = myList.rbegin(); rit != myList.rend(); ++rit) {cout << *rit << " ";
}


 

注意:begin()指向第一个元素,end()指向最后一个元素的下一个位置;rbegin()指向最后一个元素,rend()指向第一个元素的前一个位置。

2.3 容量操作
 

if(myList.empty()) {cout << "List is empty";
}
cout << "List size: " << myList.size();

2.4 元素访问
 

cout << "First element: " << myList.front();
cout << "Last element: " << myList.back();

2.5 修改操作

list提供了丰富的修改接口:

myList.push_front(0);    // 头部插入
myList.pop_front();      // 头部删除
myList.push_back(6);     // 尾部插入
myList.pop_back();       // 尾部删除auto it = myList.begin();
advance(it, 2);          // 移动到第3个位置
myList.insert(it, 99);    // 在指定位置插入
myList.erase(it);        // 删除指定位置元素myList.clear();          // 清空list

2.6 迭代器失效问题

list的迭代器在插入操作时不会失效,但在删除操作时,指向被删除元素的迭代器会失效:
// 错误示例

 

auto it = myList.begin();
while(it != myList.end()) {myList.erase(it);  // it失效后再使用++it;              // 未定义行为
}

正确写法1

while(it != myList.end()) {it = myList.erase(it);  // erase返回下一个有效迭代器
}// 正确写法2
while(it != myList.end()) {myList.erase(it++);  // 使用后置++,在删除前移动迭代器
}

3. list的模拟实现

理解list的内部实现有助于更深入地使用它。下面简要介绍关键实现要点。

3.1 节点结构

template<class T>
struct ListNode {T _data;ListNode<T>* _prev;ListNode<T>* _next;ListNode(const T& val = T()): _data(val), _prev(nullptr), _next(nullptr) {}
};

3.2 迭代器实现

list的迭代器需要对原生指针进行封装,重载相关操作符:

template<class T>
class ListIterator {
public:typedef ListNode<T> Node;typedef ListIterator<T> Self;Node* _node;ListIterator(Node* node) : _node(node) {}T& operator*() { return _node->_data; }T* operator->() { return &_node->_data; }Self& operator++() {_node = _node->_next;return *this;}Self operator++(int) {Self tmp(*this);_node = _node->_next;return tmp;}// 其他操作符重载...
};


3.3 反向迭代器

反向迭代器可以通过包装正向迭代器来实现:

template<class Iterator>
class ReverseListIterator {Iterator _it;
public:ReverseListIterator(Iterator it) : _it(it) {}auto& operator*() {Iterator tmp = _it;--tmp;return *tmp;}ReverseListIterator& operator++() {--_it;return *this;}// 其他操作符重载...
};

4. list与vector的对比

特性vectorlist
底层结构动态数组双向链表
随机访问O(1)O(n)
插入/删除尾部O(1),其他位置O(n)任意位置O(1)
空间利用率高(连续内存)低(内存碎片)
缓存友好性
迭代器失效插入/删除可能导致全部失效仅删除导致当前迭代器失效
适用场景随机访问频繁,修改少频繁插入删除,随机访问少

总结

list是C++中一个非常重要的容器,特别适合需要频繁在任意位置插入和删除元素的场景。虽然它在随机访问方面不如vector高效,但在特定场景下能提供更好的性能。理解list的内部实现机制和迭代器失效规则,可以帮助开发者避免常见错误,编写出更健壮的代码。

在实际开发中,应根据具体需求选择合适的容器。如果需要频繁随机访问,vector是更好的选择;如果需要频繁在中间位置插入删除,list则更为合适。

http://www.dtcms.com/a/311635.html

相关文章:

  • Flutter dart运算符
  • mini-swe-agent源码解读(进行中)
  • Redis 7 哈希(Hash)使用指南
  • 细分推广场景,让推客推广更贴合用户当下需求
  • 存储过程的介绍、基本语法、delimiter的使用
  • 未来交通:元宇宙技术重塑出行体验
  • 用Unity结合VCC更改人物模型出现的BUG
  • WebSocket断线重连机制:保障实时通信的高可用性
  • 疯狂星期四文案网第27天运营日记
  • 井云科技2D交互数字人:让智能服务触手可及的实用方案
  • KSP与ASM深度对比:原理、性能与使用场景
  • SpringBoot怎么查看服务端的日志
  • sqli-labs通关笔记-第28a关GET字符注入(关键字过滤绕过 手注法)
  • USB Device(VID_1f3a_PID_efe8) 驱动叹号
  • ART数据库索引结构--ART,The adaptive radix tree论文细读
  • 基于落霞归雁思维框架的软件需求管理实践指南
  • 字节Seed发布扩散语言模型,推理速度达2146 tokens/s,比同规模自回归快5.4倍
  • 【C++/STL】vector的OJ,深度剖析和模拟实现
  • Java多线程入门-基础概念与线程操作
  • JVM 01 运行区域
  • 动态规划经典模型:双数组问题的通用解决框架与实战
  • C++ STL 组件及其关系:从模块化设计到图形化展示
  • SpringBoot AOP
  • CYUSB3014-BZXC-USB3.0接口芯片-富利威
  • python---literal_eval函数
  • Python管道编程解析:构建高效数据流处理框架
  • Redis从入门到实战
  • Effective C++ 条款18:让接口容易被正确使用,不易被误用
  • IOT物联网平台发布,可私有化部署
  • 算法刷题【面试经典150题】