list
不支持通过下标访问(operator ),不支持下标加减,支持++和--(访问下一个和前一个)
迭代器的分类
- 按照功能
- iterator
- reverse_iterator
- const iterator
- consr reverse_iterator
- 按照性质:
- 单向(forward iterator):forward_list/unordered_map/unordered_set------>只支持++
- 双向(bidirectional iterator):list/map/set------>支持++/--
- 随机(random access iterator):string/vector/deque------>支持++/--/+/-
sort:只支持随机迭代器
template <class RandomAccessIterator> void sort (RandomAccessIterator first, RandomAccessIterator last);reverse :支持随机和双向
template <class BidirectionalIterator>
void reverse (BidirectionalIterator first, BidirectionalIterator last);find:都可(是InputIterator,是单向迭代器的子类)
emplace_back
- emplace_back和push_back的区别
cpp
struct A
{
public:
A(int a1=1,int a2=1)
:_a1(a1)
,_a2(a2)
{ }
private:
int _a1;
int _a2;
};
void test()
{
list<A>lt;
A a(1, 1);
lt.push_back(a);
lt.push_back(A(3, 4));//支持匿名对象
lt.emplace_back(a);
lt.emplace_back(A(3, 4));//支持匿名对象
lt.emplace_back( 3, 4 ); //支持直接传构造A的参数
}
实现中间插入
list 是不支持迭代器的+/-找到下标的,但我们也可以先通过其他方式找到下标,再insert

- 在下标为3的位置前面插入
cpp
void test1()
{
list<int>lt;
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
lt.push_back(5);
auto it = lt.begin();
int k = 3;
while (k--)
{
it++;
}
lt.insert(it, 66);
for (auto e : lt)
{
cout << e << " ";
}
cout << endl;
}
int main()
{
test1();
return 0;
}
erase
- 删除4:
- 要判断:
(it!=lt.end()),因为如果find没有找到,会返回最后一个迭代器
- 要判断:
cpp
it = find(lt.begin(), lt.end(), 4);
if(it!=lt.end())
{
lt.erase(it);
}
sort排序:升/降
-
升序:
lt.sort( ); -
降序:
greater<int>gt; lt.sort(gt);或者直接写成:
lt.sort(greater<int>())匿名对象
merge:合并链表
- A和B都是有序的才能合并
- A.merge(B)后**,B就没了**
cpp
list<int>lt;
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
lt.push_back(5);
list<int>lt2;
lt2.push_back(3);
lt2.push_back(4);
lt2.push_back(5);
lt2.push_back(6);
lt.merge(lt2);
for (auto e : lt)
{
cout << e << " ";
}
cout << endl;
unique:去重
- 必须是有序的才能使用(相同的值都挨在一起)------>先sort再去重
cpp
list<int>lt;
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
lt.push_back(5);
list<int>lt2;
lt2.push_back(3);
lt2.push_back(4);
lt2.push_back(5);
lt2.push_back(6);
lt.merge(lt2);
for (auto e : lt)
{
cout << e << " ";
}
cout << endl;
lt.unique();
for (auto e : lt )
{
cout << e << " ";
}
cout << endl;
cpp
1 2 3 3 4 4 5 5 6
1 2 3 4 5 6
remove:删除
传的是值,不是迭代器
cpp
lt.remove(2);
lt.remove(3);
splice:转移元素
3种用法:(被转移的结构的对应元素会消失)
cpp
entire list (1) //转移整个链表
void splice (iterator position, list& x);
single element (2) //转移单个迭代器位置的元素
void splice (iterator position, list& x, iterator i);
element range (3) //转移某个范围
void splice (iterator position, list& x, iterator first, iterator last);
举例:
构建一个1,2,3,4,5,6的链表:
cpplist<int>lt; lt.push_back(1); lt.push_back(2); lt.push_back(3); lt.push_back(4); lt .push_back(5); lt .push_back(6);
- 将某个数字移到开头:
cppint x = 0; cin >> x; auto it = find(lt.begin(),lt.end(), x); ///void splice (iterator position, list& x, iterator i); lt.splice(lt.begin(), lt, it);
- 将某个数字及其之后的所有数字移到开头:
cppint x = 0; cin >> x; auto it = find(lt.begin(),lt.end(), x); ///void splice (iterator position, list& x, iterator first, iterator last); lt.splice(lt.begin(), lt, it, lt.end());
实现
list.h
在namespace lcj中,创建class list
- 先实现链表节点
list_node,为一个结构体(类),其中存 内容,上一个节点指针,下一个节点指针 - 实现list类:
list
cpp
namespace lcj
{
template<class T>
class list_node
{
T _data;
list_node<T>* _prev;
list_node<T>* _next;
};
template<class T>
class list
{
typedef list_node<T> Node;
public:
private:
Node* _head;
};
}
1.构造函数:
- 创建节点
- 将节点中的前后指针加上
_head = new Node; _head->_next = _head; _head->_prev = _head;
cpp
namespace lcj
{
template<class T>
class list_node
{
T _data;
list_node<T>* _prev;
list_node<T>* _next;
};
template<class T>
class list
{
typedef list_node<T> Node;
public:
list()//////////////////////////////////////////////////////////////
{
_head = new Node;
_head->_next = _head;
_head->_prev = _head;
}
private:
Node* _head;
};
}
2.实现尾插:
实现size()和empty()
为了计数方便,增加_size
cpp
template<class T>
class list
{
typedef list_node<T> Node;
public:
private:
Node* _head;
size_t _size;/////////////////////////////////////////////////////////////
};
push_back
cpp
template<class T>
class list
{
typedef list_node<T> Node;
public:
list()
{
_head = new Node;
_head->_next = _head;
_head->_prev = _head;
_head->_size =0;
}
void push_back(const T& x)
{
Node* newnode = new Node(x);
Node* tail = _head->_prev; // 先拿到原来的尾节点
newnode->_next = _head; // 新节点的后继指向头节点
newnode->_prev = tail; // 新节点的前驱指向旧尾
tail->_next = newnode; // 旧尾的后继指向新节点
_head->_prev = newnode; // 头节点的前驱指向新节点
++_size;
}
size_t size() const///////////////////////////
{
return _size;
}
bool empty() const//////////////////////////////
{
return _size == 0;
}
private:
Node* _head;
size_t _size;
};
3.实现迭代器
为什么要自己实现一个迭代器,因为list的节点在内存中不是线性存储的。如果是原来迭代器的一些操作,比如++、--,可能造成访问越界,所以我们要自己实现一个类,从而实现List的迭代器对应的操作
运算符重载函数,是专门为类类型准备的------>参数至少有一个自定义类型:不能参数全是 int、double 这种内置类型, 防止你修改 C++ 原本的语法。
代码+逐句讲解‼️
cpp
template<class T>
struct list_iterator//迭代器的类
{
typedef list_node<T> Node;//简化节点名称
Node* _node;//这是整个迭代器这个类中 唯一的成员变量
//为什么要有这个成员变量呢?
//因为我们知道迭代器的作用就是返回一个节点的指针,
//所以我们创造这个成员变量,
//然后呢,在后面的操作中直接对这个指针进行修改,
// 然后可以直接返回它
typedef list_iterator Self; //简化迭代器这个名字,在迭代器最低的类中,就叫self
list_iterator(Node* node)//迭代器这个类的 构造函数------>支持list类中的这样 iterator it(_head->_next);的使用。用来在类外把对应的节点指针变成迭代器
:_node(node)
{ }
T& operator*()//*解引用的运算符重载,直接返回list对应的数据_data
{
return _node->_data;
}
Self operator++()//返回下一个节点的迭代器,返回的是迭代器这个类, // 必须返回自身引用,符合STL迭代器规范
{
_node = _node->_next;
return *this;
}
Self& operator++()
{
_node = _node->_next;
return *this;
}
Self& operator--()
{
_node = _node->_prev;
return *this;
}
bool operator!=(const Self& s)
{
return _node != s._node;
}
bool operator==(const Self& s)const
{
return _node == s._node;
}
};
struct 和class:
- struct类,不加访问限定符,纯公有
- class,不加,纯私有
1.为什么list_node用 struct?
节点类是一个纯数据结构 ,它的三个成员_data、_prev、_next,需要被list类和list_iterator类随时随地直接读写。
2. 为什么list_iterator用 struct?
它的核心成员_node指针,需要被list类的成员函数(begin()、end()、insert()、erase())直接访问。比如:
``bool operator!=(const Self& s){return _node != s._node; }
把list_node改为struct
cpp
struct list_node
{
T _data;
list_node<T>* _prev;
list_node<T>* _next;
};
test_list1()
cpp
void test_list1()
{
list<int> lt;
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
list<int>::iterator it = lt.begin();
while (it != lt.end())
{
cout << *it << " ";
++it;
}
cout << endl;
}
push_back上面说了,
接下来,想要实现:list<int>::iterator it = lt.begin();,就要先实现
- 迭代器iterator
- begin函数
-
Iterator是我们自己定义的一个类:
struct list_iterator//迭代器,然后再list这个类中typedef出来的名称-
我们是这样创建list的迭代器的,
list<int>::iterator it = lt.begin();,但看起来这个iterator它是在list类这个类里面的,可是我们知道并不是这样,------>因为
list类内部有一个typedef(类型别名),把外部的list_iterator<T>重命名成了内部的iterator。------>编译器会自动把它翻译成:
list_iterator<int> it = lt.begin();
-
构造函数的对比
-
每一个类都有对应的构造函数
-
构造一个节点的时候
cpplist_node(const T& data = T()) :_data(data) ,_next(nullptr) ,_prev(nullptr) { } -
构造一个list的时候
cpplist() { _head = new Node(T()); _head->_next = _head; _head->_prev = _head; _size = 0; } -
构造一个迭代器的时候
因为我们在实现begin、 and的时候,一般是这样的:
iterator it(_head->_next);return it;,所以迭代器的构造函数要是带参的
cpplist_iterator(Node* node) :_node(node) { }
-
4.前一部分总代码+逐句讲解‼️
指针类型直接转化成了一个iterator这个类类型,相当于内置类型转化成类类型, 条件就是类有对应的构造函数就可以
cpp
namespace lcj
{
/////////////////////////////////////////////////////////////////////////////////////////////
template<class T>
struct list_node//节点的类
{
T _data;
list_node<T>* _prev;
list_node<T>* _next;
list_node(const T& data = T())//节点的实现,是一个默认 构造函数, 并且同时支持你传参和不传参都可以生成对应的节点
:_data(data)
,_next(nullptr)
,_prev(nullptr)
{ }
};
/////////////////////////////////////////////////////////////////////////////////////////////
template<class T>
struct list_iterator//迭代器的类
{
typedef list_node<T> Node;//简化节点名称
Node* _node;//这是整个迭代器这个类中 唯一的成员变量,是一个节点的指针。因为像是 ++、--、*这些操作,都需要通过这个指针找到对应的节点(Node* 类型),然后返回对应的迭代器
typedef list_iterator Self; //在自己这个类中简化自己这个类的名称,然后在后面的++、--中,返回时也写得更方便一些
//传参传的是(_head->_next)这样的节点指针。
//用来在类外把对应的节点指针变成list_iterator迭代器这种类
list_iterator(Node* node)//迭代器这个类的 构造函数------>支持list类中的这样 iterator it(_head->_next);的使用
:_node(node)
{ }
T& operator*()//*的运算符重载,直接返回list对应的_data
{
return _node->_data;
}
Self& operator++()//++的运算符重载,返回对应的迭代器
{
_node = _node->_next;
return *this;
}
bool operator!=(const Self& s)//通过判断迭代器类(list_iterator)创建的对象 中唯一的成员变量_node ,来判断两个迭代器类(list_iterator)是否是相同的迭代 类 对象(list_iterator)
{
return _node != s._node;
}
};
/////////////////////////////////////////////////////////////////////////////////////////////
template<class T>
class list // 链表的类
{
typedef list_node<T> Node;//简化链节的写法
public:
list()// 构造函数,生成一个只有头节点的list
{
_head = new Node(T());
_head->_next = _head;
_head->_prev = _head;
_size = 0;
}
typedef list_iterator<T> iterator;//简化迭代器的写法,符合STL
iterator begin()//通过 节点指针,创造出一个迭代器类(iterator),然后返回这个迭代器类
{
iterator it(_head->_next);
return it;//编译器会做值拷贝,把局部迭代器里的_node指针复制给外面接收的变量
}
iterator end()//指向哨兵头节点(最后一个节点的下一个节点),作为遍历结束的标志,创造出一个迭代器类(iterator),然后返回这个迭代器类
{
return _head;
}
void push_back(const T& x)
{
Node* newnode = new Node(x);//创建节点,并且调用带参构造函数
Node* tail = _head->_prev; // 先拿到原来的尾节点
newnode->_next = _head; // 新节点的后继指向头节点
newnode->_prev = tail; // 新节点的前驱指向旧尾
tail->_next = newnode; // 旧尾的后继指向新节点
_head->_prev = newnode; // 头节点的前驱指向新节点
++_size;
}
size_t size()
{
return _size;
}
bool empty() const
{
return _size == 0;
}
private:
Node* _head;
size_t _size;
};
void test_list1()
{
list<int> lt;
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
list<int>::iterator it = lt.begin();
while (it != lt.end())
{
cout << *it << " ";
++it;
}
cout << endl;
}
}
5.实现insert
通过insert实现push_front和push_back
cpp
void insert(iterator pos, const T& x)
{
Node* cur = pos._node;///这里应该写成.而不是->,因为 pos是个类(结构体),_node是结构体的成员变量
Node* prev = cur->_prev;
Node* newnode = new Node(x);
newnode->_next = cur;
cur->_prev = newnode;
newnode->_prev = prev;
prev->_next = newnode;
++_size;
}
void push_front(const T& x)
{
insert(begin(), x);
}
void push_back(const T& x)
{
insert(end(), x);
}
6.实现erase
通过erase实现pop_back
通过erase实现pop_front
cpp
void erase(iterator pos)
{
assert(pos != end());///end是哨兵位头节点
///迭代器只是一个类,想要访问对应的节点需要访问其中的_node成员变量
Node* prev = pos._node->_prev;
Node* next= pos._node->_next;
prev->_next = next;
next->_prev = prev;
delete pos._node;
--_size;
}
void pop_back()
{
erase(--end());
}
void pop_front()
{
erase(begin());
}
7.重载->
想打印一个结构体的类,而且
如下,我定义了一个结构体struct AA,创建了对应的list:list<AA> lta,
想打印,
- 方法一:当然可以先:
list<AA>::iterator it = lta.begin();,找到对应元素的指针(AA类的指针),然后解引用,得到一个AA类,然后通过"."来访问对应的_a1和_a2 - 方法二:list的迭代器,就是一个结构AA对象的地址------>通过"->",像访问一个结构体一样访问不行吗?不行🙅♀️,因为这时候list的迭代器并不是地址,而是一个类,所以不能用"->"
cpp
struct AA
{
int _a1=1;
int _a2=2;
};
list<AA> lta;
lta.push_back(AA());
lta.push_back(AA());
lta.push_back(AA());
lta.push_back(AA());
lta.push_back(AA());
list<AA>::iterator it = lta.begin();
while (it != lta.end())
{
///使用.的方法
cout << (*it)._a1 << " : " << (*it)._a2 << endl;
❌❌❌///使用->的方法:重载
cout<< it->_a1 << " : " << _a2 << endl;
}
cout << endl;
实现
‼️operator->必须返回指向数据的指针 ,而我之前犯错:返回的了数据本身(_node->_data是T类型,不是T*)。
实际上的访问应该是这样的:
cout << it.operator->()->_a1 << " : " << it.operator->()->_a1 << endl;
it.operator->()返回对应的_data的指针,->_a1相当于就是对结构体指针进行了"->"操作
但是编辑器省略了一个"->",只需要这样写就行:
cout<< it->_a1 << " : " << it->_a2 << endl;
cpp
///list_iterator 模板
template<class T>
struct list_iterator
{
typedef list_node<T> Node;
typedef list_iterator Self;
Node* _node;
T* operator->()/////////////////////////////////////////////////////////////////
{
return & _node->_data; ///operator->必须返回指向数据的指针
}
};
..................
struct AA
{
int _a1=1;
int _a2=2;
};
void test_list1()
{
list<AA> lta;
lta.push_back(AA());
lta.push_back(AA());
lta.push_back(AA());
lta.push_back(AA());
lta.push_back(AA());
list<AA>::iterator it = lta.begin();
while (it != lta.end())
{
///使用.的方法
cout << (*it)._a1 << " : " << (*it)._a2 << endl;
///使用->的方法:重载
cout<< it->_a1 << " : " << it->_a2 << endl;
++it;
}
cout << endl;
}
8.实现const_iterator
之前我们在实现vector中实现的print_container在这里用不了了,原因是没有实现const迭代器
cpp
template<class Container>
void print_container(const Container& con)//两遍打印
{
list<int>::const_iterator it = con.begin();
while (it != con.end())
{
//*it += 10;
cout << *it << " ";
++it;
}
cout << endl;
for (auto& e : con)
{
//e *= 10;
cout << e << " ";
}
cout << endl;
}
8.1为什么要实现const迭代器const_iterator而不是const iterator?
因为const修饰iterator,是iterator不能修改,
而const_iterator代表这个迭代器指向的内容不能修改
8.2如何实现?
最基础的理解:
------>对迭代器进行修改的list_iterator 类模板 中的成员函数,只有"解引用"和"箭头访问->"两个函数可能对迭代器指向的内容进行修改*
------>那只要修改这两个函数就行了:
cpp
//原来的:
T& operator*()
{
return _node->_data;
}
T* operator->()
{
return & _node->_data; ///注意 :返回的是T* 指针,不是T的引用
}
//修改后的:
const T& operator*()
{
return _node->_data;
}
const T* operator->()
{
return & _node->_data; ///注意 :返回的是T* 指针,不是T的引用
}
❌‼️但不能直接这样改,这样导致普通迭代器的解引用和箭头访问也失效了
8.3‼️两个模板类的版本实现const_iterator
✅实现两个不同的模板类,list_iterator 模板 类 和 list_const_iterator 模板 类
cpp
///list_iterator 模板
template<class T>
struct list_iterator
{
typedef list_node<T> Node;
typedef list_iterator Self;
Node* _node;
list_iterator(Node* node)
:_node(node)
{ }
T& operator*()
{
return _node->_data;
}
T* operator->()
{
return & _node->_data; ///注意 :返回的是T* 指针,不是T的引用
}
Self& operator++()
{
_node = _node->_next;
return *this;
}
Self& operator--()
{
_node = _node->_prev;
return *this;
}
bool operator!=(const Self& s) const
{
return _node != s._node;
}
bool operator==(const Self& s)const
{
return _node == s._node;
}
};
///list_const_iterator 模板
template<class T>
struct list_const_iterator
{
typedef list_node<T> Node;
typedef list_const_iterator Self;
Node* _node;
list_const_iterator(Node* node)
:_node(node)
{ }
const T& operator*()
{
return _node->_data;
}
const T* operator->()
{
return & _node->_data; ///注意 :返回的是T* 指针,不是T的引用
}
Self& operator++()
{
_node = _node->_next;
return *this;
}
Self& operator--()
{
_node = _node->_prev;
return *this;
}
bool operator!=(const Self& s) const
{
return _node != s._node;
}
bool operator==(const Self& s)const
{
return _node == s._node;
}
};
当然,list模板中也要修改:
cpp
///list 模板
template<class T>
class list
{
typedef list_node<T> Node;
public:
typedef list_iterator<T> iterator;
typedef list_const_iterator<T> const_iterator;/////////////////////////////
iterator begin()
{
iterator it(_head->_next);
return it;
}
iterator end()
{
return _head;
}
const_iterator begin()const ////////////////////////////////////////////////////////////
{
const_iterator it(_head->_next);/////////////////////////////////////改iterator为const_iterator
return it;
}
const_iterator end()const//////////////////////////////////////////////////////////////
{
return _head;
}
const的辨析:
const_iterator:看后面
const的位置 |
作用 | 核心规则 |
|---|---|---|
| 返回值类型前 | 修饰返回值本身,表示返回值不能被修改 | ++只有返回引用 / 指针时才有意义++ ,返回值类型(如int、bool)加了没用 |
| 函数参数前 | 修饰形参,表示函数内部不能修改这个形参 | 传类对象时必须加const&,既避免拷贝又保护实参 |
| 函数末尾 | 只能加在类的成员函数 后面,修饰this 指针 | 表示这个函数不能修改类的任何成员变量 |
✅ 形参的const:
- 形参是普通变量:
void func(const int x)→ x 在函数内部不能改 - 形参是类对象:
void func(const list<int>& lt)→ lt 在函数内部不能改,且只能调用 lt 的 const 成员函数 - 形参是指针:
void func(const int* p)→ 不能通过 p 修改指向的内容,(不能解引用修改和通过"->"修改)
| 操作 | 是否允许 | 原因 |
|---|---|---|
p = &b; |
✅ 可以 | 指针本身可以指向其他地址 |
int a = *p; |
✅ 可以 | 可以读取指向的内容 |
*p = 100; |
❌ 不可以 | 不能通过 p 修改指向的内容 |
(*p)++; |
❌ 不可以 | 不能通过 p 修改指向的内容 |
p++; |
✅ 可以 | 指针本身可以移动 |
✅函数末尾的const:
- 普通成员函数的 this 指针是:
T* const this→ 指针本身不能改,指向的内容可以改 - 末尾加 const 的成员函数的 this 指针是:
const T* const this→ 指针本身和指向的内容都不能改
8.5‼️彻底搞懂const_iterator
1.给谁用:
const 类对象
cpp
// 普通对象
list<int> lt;
list<int>::iterator it = lt.begin();
*it = 100; // ✅
// const对象,不能修改
const list<int> clt = lt;
list<int>::iterator it = clt.begin(); // ❌
list<int>::const_iterator cit = clt.begin(); // ✅
*cit = 200; // ❌ const_iterator指向的内容不能改
2. 为什么有const_iterator?
const对象不能修改,而普通迭代器可以访问并修改,故普通iterator不行‼️
3.const_iterator vs const iterator
| 类型 | 迭代器本身能不能改(++、--) | 指向的内容能不能改(*it = x) |
|---|---|---|
iterator |
✅ 可以 | ✅ 可以 |
const_iterator |
✅ 可以 | ❌ 不可以 |
const iterator |
❌ 不可以 | ✅ 可以 |
const const_iterator |
❌ 不可以 | ❌ 不可以 |
4. 为什么const_iterator的operator*返回const T&,但函数末尾没加 const?
对象+const
- 普通对象(非 const 对象)既可以调用 const 成员函数,也可以调用非 const 成员函数。
- const 对象只能调用 const 成员函数
operator++会修改迭代器自己的_node成员,所以它绝对不能加 const。(不然const成员也能用了,不行)- 因为
const_iterator也只是一种特殊的迭代器啊,实现的功能和iterator是相同的,都是++/--/*
5.函数末尾加 const 和返回值加 const 有没有必然联系?
没有‼️
但有一个注意点:
cpp
class A
{
public:
int& get_a() const//❌
{
return _a;
}
private:
int _a = 10;
};
int main()
{
const A a;
a.get_a() = 20; // ❌ 竟然修改了const对象的成员!权限放大了
return 0;
}
int& get_a()函数后面加了const,代表不论是普通对象还是const对象都能调用来得到_a的引用,自然也都能直接修改_a‼️,如果是const对象,这自然是错的
✅正确写法:
cppconst int& get_a() const { return _a; }
8.6‼️通过模板实现
因为两个iterator模板重复度太高,所以直接传不同的地方对应的内容到模板里面来生成不同的类
先来比较一下吧:
list模板
- 原来的list模板
cpp
///list 模板
template<class T>
class list
{
public:
typedef list_iterator<T> iterator;
};
- 现在的list模板
cpp
///list 模板
template<class T>
class list
{
public:
/* typedef list_iterator<T> iterator;
typedef list_const_iterator<T> const_iterator;*/
typedef list_iterator<T, T& , T*> iterator;
typedef list_iterator<T,const T&,const T*> const_iterator;
};
list_iterator 模板
- 原来的
list_iterator(和list_const_iterator模板)模板- 实现了两个类模板,而大部分函数都一样,只有
operator*()和operator->()有区别
- 实现了两个类模板,而大部分函数都一样,只有
太长了就不写了,上面 "++8.3两个模板类的版本实现const_iterator++ "有写,唯三的区别在下面:
cpp///list_iterator 模板 template<class T> struct list_iterator { ➡️list_iterator(Node* node) :_node(node) { } ➡️T& operator*() { return _node->_data; } ➡️T* operator->() { return & _node->_data; ///注意 :返回的是T* 指针,不是T的引用 } }; ///list_const_iterator 模板 template<class T> struct list_const_iterator { ➡️list_const_iterator(Node* node) :_node(node) { } ➡️const T& operator*() { return _node->_data; } ➡️const T* operator->() { return & _node->_data; ///注意 :返回的是T* 指针,不是T的引用 } };
现在的list_iterator 类模板:
cpp
///list_iterator 模板
template<class T, class Ref, class Ptr>
struct list_iterator
{
typedef list_node<T > Node;
typedef list_iterator<T, Ref, Ptr> Self;
Node* _node;
➡️list_iterator(Node* node)
:_node(node)
{ }
➡️Ref operator*()
{
return _node->_data;
}
➡️Ptr operator->()
{
return & _node->_data; ///注意 :返回的是T* 指针,不是T的引用
}
Self& operator++()
{
_node = _node->_next;
return *this;
}
Self& operator--()
{
_node = _node->_prev;
return *this;
}
bool operator!=(const Self& s) const
{
return _node != s._node;
}
bool operator==(const Self& s)const
{
return _node == s._node;
}
};