目录
一、list的介绍
二、list的使用
2.1 Construct
2.2 operator=
2.3 Iterators
2.4 Capacity
2.5 Element access
2.6 Modifiers
2.7 Operations
有数据结构作为基础,STL 上手很快,学习成本也低,本文也是讲解 list 常用重点接口,其它有需要再查询文档,重点也是放在 list 的模拟实现上面
list 文档介绍
template < class T, class Alloc = allocator > class list;
class Alloc = allocator
使用 list 要包含 list 的头文件:
#include
list 要重点使用迭代器了,因为 list 不能支持随机访问了,即不能使用 “[]” + 下标 进行访问
list 也是掌握一些常用的接口,其它有需要在查询文档
先说一下成员变量
value_type 就是第一个模板参数 (T);size_type 与 size_t 的用法一致,无符号
接口简单说明:
构造函数 接口说明 list (size_type n, const value_type& val = value_type()) 构造的list中包含n个值为val的元素 list() 构造空的list list (const list& x) 拷贝构造函数 list (InputIterator first, InputIterator last) 用[first, last)区间中的元素构造list
构造某个类型的 list
list l1;//构造int类型的list
list l2;//构造double类型的list
测试代码
void Test_list()
{list l1; // 构造空的l1list l2(10, 3); // l2中放10个值为3的元素list l3(l2.begin(), l2.end()); // 用l2的[begin(), end())左闭右开的区间构造l3list l4(l3); // 用l3拷贝构造l4//以数组为迭代器区间构造l5int array[] = { 1,2,3,4 };list l5(array, array + sizeof(array) / sizeof(int));
}
测试代码
void Test_list()
{list l1(10, 3);// l1中构造10个值为3的元素list l2 = l1;//赋值重载list l3;l3 = l1;//赋值重载
}
析构函数不解释了,程序结束自动调用
list 的迭代器不再是简单的原生指针了,指针要经过封装和重载才能支持 list 的迭代器的使用,范围 for 的底层就是迭代器。此处可暂时将迭代器理解成一个指针,该指针指向list中的某个节点,到 list 模拟实现再细讲
常用接口
函数声明 接口说明 begin 返回第一个元素的迭代器 end 返回最后一个元素下一个位置的迭代器 rbegin 返回第一个元素的reverse_iterator,即end位置 rend 返回最后一个元素下一个位置的reverse_iterator,即begin位置
示意图
注意:遍历 list 只能用迭代器和范围for
测试代码
void Test_list()
{int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };list l(array, array + sizeof(array) / sizeof(array[0]));list::iterator it = l.begin();//迭代器判断结束只能使用 !=while (it != l.end()){cout << *it;++it;}cout << endl;for (auto e : l){cout << e;}cout << endl;
}
运行结果
注意:迭代器判断结束条件只能使用 != ,因为 list 的每个节点的空间的大小是不确定的,不能使用 it < l.end();之前 vector 和 string 的迭代器结束可以使用 < 判断迭代器结束,因为它们的空间是连续的
反向迭代器使用
void Test_list()
{int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };list l(array, array + sizeof(array) / sizeof(array[0]));list::reverse_iterator it = l.rbegin();//迭代器判断结束只能使用 !=while (it != l.rend()){cout << *it;++it;}cout << endl;}
注意
- begin与end为正向迭代器,对迭代器执行++操作,迭代器向后移动
- rbegin(end)与rend(begin)为反向迭代器,对迭代器执行++操作,迭代器向前移动
运行结果
常用接口
函数声明 接口说明 empty 检测 list 是否为空,是返回 true,否则返回 false size 返回 list 中有效节点的个数
不演示,直接使用即可
常用接口
函数声明 接口说明 front 返回list的第一个节点中值的引用 back 返回list的最后一个节点中值的引用
测试代码
void Test_list()
{int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };list l(array, array + sizeof(array) / sizeof(array[0]));cout << l.front() << endl; //1cout << l.back() << endl; //0
}
运行结果
常用接口
函数声明 接口说明 push_front 在list首元素前插入值为val的元素 pop_front 删除list中第一个元素 push_back 在list尾部插入值为val的元素 pop_back 删除list中最后一个元素 insert 在list position位置中插入值为val的元素 erase 删除list position位置的元素 swap 交换两个list中的元素 clear 清空list中的有效元素
测试代码
void Test_list()
{list l;l.push_back(1);//尾插数据l.push_back(2);l.push_back(3);l.push_back(4);for (auto e : l)cout << e;cout << endl;l.pop_back();//删除 4for (auto e : l)cout << e;cout << endl;l.push_front(0);//头插0for (auto e : l)cout << e;cout << endl;l.pop_front();//头删for (auto e : l)cout << e;cout << endl;
}
运行结果
erase
测试代码
void Test_list()
{int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };list l(array, array + sizeof(array) / sizeof(array[0]));list::iterator pos = find(l.begin(), l.end(), 2);l.erase(pos); //删除2for (auto e : l)cout << e;cout << endl;
}
运行结果
insert
测试代码
void Test_list()
{int array[] = { 1, 2, 4, 5, 6, 7, 8, 9 };list l(array, array + sizeof(array) / sizeof(array[0]));list::iterator pos = find(l.begin(), l.end(), 4);l.insert(pos, 3); //在4的位置的前一个插入3for (auto e : l)cout << e;cout << endl;
}
运行结果
list 的迭代器失效问题
前面说过,此处可将迭代器暂时理解成类似于指针,迭代器失效即迭代器所指向的节点的无效,即该节点被删除了。因为 list 的底层结构为带头结点的双向循环链表,因此在 list 中进行插入时是不会导致list的迭代器失效的,只有在删除时才会失效,并且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响
所以 insert 并不会造成迭代器失效,而 erase 之后则会造成 pos 迭代器失效,因为 pos 迭代器指向的空间已经被释放了
测试代码
void Test_list()
{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 Test_list()
{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);}
}
修改之后,程序就可以正常运行了
这些接口不怎么使用,就不介绍了,有需要再查询文档,其中的 sort 排序数据量大的时候,效率低,也不怎么使用
----------------我是分割线---------------
文章到这里就结束了,下一篇即将更新
上一篇:【MyBatis】查询语句汇总
下一篇:C++ 入门基础