一、模拟实现list迭代器
在STL中vector和string的迭代器都是使用的原生指针,但是由于双向链表不是连续的所以无法使用原生指针充当迭代器。所以,我们为list创建了一个自定义类型迭代器。首先创建一个类模板表示节点。
链表节点
//创建一个自定义类型模板作为节点;这个自定义类型的类型是ListNode<T>
template <class T>
struct ListNode {
//创建指针指向前一个节点
ListNode* _prev;
//创建指针指向下一个节点
ListNode* _next;
//创建存储数据
T _data;
ListNode(const T& val = T()) :
_prev(nullptr)
, _next(nullptr)
, _data(val)
{}
};
注意:
普通自定义类的类型是类名;
自定义类模板的类型是类名<T>,T根据实际情况确定;
自定义迭代器
//创建迭代器类模板
template <class T>
class _list_iterator {
//重新定义变量名
typedef ListNode<T> Node;
//封装函数
public:
//最起码要有个构造函数吧,函数输入是结构体指针
_list_iterator(Node*& x)
:_node(x)
{}
//重载运算符++
_list_iterator<T>& operator++() {
_node = _node->_next;
return *this;
}
_list_iterator<T> operator++(int) {
_list_iterator tmp(*this);
_node = _node->_next;
return tmp;
}
//重载运算符*
T& operator*() {
return _node->_data;
}
//重载运算符!=
bool operator !=(const _list_iterator& x) {
return _node != x._node;
}
bool operator ==(const _list_iterator& x) {
return _node == x._node;
}
//创建私有化成员变量
private:
//指针的成员变量应该是ListNode的指针
Node* _node;
};
注意:
不需要析构函数 -- 节点不属于迭代器,不需要迭代器释放
拷贝构造和赋值重载 -- 默认生成的浅拷贝就可以(迭代器本身就是指针压根不需要深拷贝)
后加加需要一个int类型的参数,并且由于后加加返回的是临时变量,所以选择传值返回;
二、模拟实现list
list简单模拟实现
//创建双向链表list类模板
template <class T>
class list {
//重新定义变量名
typedef ListNode<T> Node;
//封装函数
public:
typedef _list_iterator<T> iterator;
//创建一个无参构造器
list() {
//_phead只是一个野指针,现在初始化一块空间给它
_head = new Node; //new之前会调用ListNode的构造函数初始化
_head->_next = _head;//哨兵位上一个节点和下一个节点都是自己;
_head->_prev = _head;
}
//迭代器起始位置
iterator begin() {
return iterator(_head->_next);
//为什么是传值返回?iterator本质上还是指针,指向某一个节点。
//这个节点的空间通过析构函数释放,iterator根本管不到
}
iterator end() {
iterator tmp(_head);
return tmp;
}
//尾插
void push_back(const T& x) {
//找到尾节点
Node* tail = _head->_prev;
//创建新节点
Node* newnode = new Node(x);
//调整节点指向
tail->_next = newnode;
newnode->_prev = tail;
newnode->_next = _head;
_head->_prev = newnode;
}
private:
//哨兵位的指针
Node* _head;
};
验证迭代器
example:
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())
{
std::cout << *it << " ";
it++;
}
std::cout << std::endl;
}
result:
1 2 3 4
三、迭代器与指针
example:
void fun() {
//创建一个原生指针
Node* pnode = _head->_next;
//创建迭代器
iterator it(_head->_next);
*pnode;//对原生指针解引用
*it;//对迭代器解引用
++pnode;//对原生指针++
++it;//对迭代器++
}
result:
++之前:
++之后:
pnode是一个结构体指针而it是一个迭代器对象 ,他们占用的空间一样大都是4字节(32位系统),并且存的值也是一样的,但他们使用运算符的意义和结果不同。*pnode返回的是一个结构体List Node,it返回的是ListNode里面的_data;++之后pnode变成了野指针,it变成了指向下一个节点的迭代器。