库里面的链表如下

cplusplus.com/reference/list/list/?kw=list
首先可以知道的是,库里面的list是双向循环链表,那么在定义节点时,就有三个成员,指向上一个节点的prev,指向下一个节点的next和节点本身的数据。当想要存储各种类型时,为避免代码冗余和增加我们的工作量,使用模板就可以很好的适配出我们想要的类型
cpp
template<class T>
struct ListNode
{
ListNode(const T& val = T())
: _prev(nullptr)
, _next(nullptr)
, _val(val)
{}
ListNode<T>* _prev;
ListNode<T>* _next;
T _val;
};
和vector一样,list也是一种容器,但vector的迭代器很容易实现,因为vector的物理空间都是连续的,而物理空间不连续的list容器,它的迭代器的实现不简单。
在list迭代器中,我们期望他完成++,--,*等操作,而在判断迭代器是否继续走时时,不应该用<来判断,list不连续所以只能用!=操作判断。
但还有一种情况,如果list迭代器指向的内容,只读而不能修改它,那该怎么办?
方法一:使用const_iterator
cpp
#include <list>
#include <iostream>
int main() {
std::list<int> myList = {1, 2, 3, 4, 5};
for (std::list<int>::const_iterator it = myList.cbegin(); it != myList.cend(); ++it) {
std::cout << *it << " ";
}
for (auto it = myList.cbegin(); it != myList.cend(); ++it) {
std::cout << *it << " ";
}
}
方法二:使用const引用或const容器
如果容器本身是由const修饰的,他的迭代器会自动变成const_iterator
cpp
const std::list<int> myList = {1, 2, 3, 4, 5};
for (auto it = myList.begin(); it != myList.end(); ++it) {
std::cout << *it << " "; // 只读
// *it = 10; // 错误
}