13 选 list 还是 vector?C++ STL list 扩容 / 迭代器失效问题 + 模拟实现,对比后再做选择
1 list 类
1.1 底层数据结构--双向循环链表
环形结构:
-
哨兵节点的
next
指向第一个实际节点 -
哨兵节点的
prev
指向最后一个实际节点 -
最后一个节点的
next
指向哨兵节点 -
第一个节点的
prev
指向哨兵节点
1.2 构造函数的底层行为--都先创建一个哨兵位节点
void empty_init(){_head = new Node;//new自定义类型,自定义类型会调用默认构造函数创建哨兵位节点_head->_prev = _head;//前驱指针指向自己_head->_next = _head;//后驱指针指向自己_size = 0;}list() {empty_init();}
1.3 list iterator的使用
只支持顺序遍历,不支持随机访问---地址加偏移量来访问因为底层结构是链式的,一个一个节点分开的。
-
begin与end为正向迭代器,对迭代器执行++操作,迭代器向后移动
-
rbegin(end)与rend(begin)为反向迭代器,对迭代器执行++操作,迭代器向前移动
1.4 list的迭代器失效
前面说过,此处大家可将迭代器暂时理解成类似于指针,迭代器失效即迭代器所指向的节点的无 效,即该节点被删除了。因为list的底层结构为带头结点的双向循环链表,因此在list中进行插入 时是不会导致list的迭代器失效的,只有在删除时才会失效,并且失效的只是指向被删除节点的迭 代器,其他迭代器不会受到影响。
void TestListIterator1(){ int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; list l(array, array+sizeof(array)/sizeof(array[0])); auto it = l.begin(); while (it != l.end()) { // erase()函数执行后,it所指向的节点已被删除,因此it无效,在下一次使用it时,必须先给其赋值 l.erase(it); ++it; }}// 改正void TestListIterator(){ int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; list l(array, array+sizeof(array)/sizeof(array[0])); auto it = l.begin(); while (it != l.end()) { l.erase(it++); // it = l.erase(it); }}
1.5 list与vector的对比
vector与list都是STL中非常重要的序列式容器,由于两个容器的底层结构不同,导致其特性以及 应用场景不同,其主要不同如下:
2 list的使用和简单模拟实现gitee链接:
c++基础/c++List(链表)/Project1/List.h · 坤坤/c++入门代码及笔记 - 码云 - 开源中国