目录
一、迭代器是什么
二、迭代器的本质
三、如何给一个容器实现迭代器功能
四、正向迭代器功能的具体实现
五、反向迭代器
六、list底层代码剖析
一、迭代器是什么
迭代器(iterator)有时又称光标(cursor)是程序设计的软件设计模式,可在容器对(container,例如链表或数组)上遍访的接口,设计人员无需关心容器对象的内存分配的实现细节。
各种语言实现迭代器的方式皆不尽同,有些面向对象语言像Java,C#,Ruby,Python,Delphi都已将迭代器的特性内置语言当中,完美的跟语言集成,我们称之隐式迭代器(implicit iterator),但像是C++语言本身就没有迭代器的特色,但STL仍利用模板实现了功能强大的迭代器。STL容器的数据的内存地址可能会重新分配(reallocate),与容器绑定的迭代器仍然可以定位到重新分配后的正确的内存地址。
二、迭代器的本质
迭代器的本质其实就是指针 (vector、string) ,或者是对指针的进一步封装(list)
三、如何给一个容器实现迭代器功能
① 对原生态指针进行封装,实现一个迭代器的类
② 在容器中给迭代器类型取别名 iterator,为了方便用户操作
③ 容器中增加begin() 、end()接口
④ 迭代器类中实现解引用 * 和 -> 元素访问功能
⑤ 迭代器类中实现迭代器移动功能 ++(以及--)
⑥ 迭代器类中实现比较功能 == 和 !=
四、正向迭代器功能的具体实现
① T Ptr Ref 分别为迭代器中对应不同类型的模板参数 对应这解引用*与->俩个下标运算法不同的操作返回值类型
② self (本身) 是作为ListIterator<T, Ptr, Ref> 的一个别名,方便于函数的返回,如下,二者是完全一致的
template<class T, class Ptr, class Ref>
class ListIterator
{
typedef ListNode<T> Node;
typedef ListIterator<T, Ptr, Ref> self;
public:
ListIterator(Node* pNode = nullptr)
: _pNode(pNode)
{}
/
/// 解引用
Ref operator*()
{
return _pNode->val;
}
Ptr operator->()
{
return &(_pNode->val);
}
/
/// ++ --
self& operator++()
{
_pNode = _pNode->next;
return* this;
}
self operator++(int)
{
self temp(*this);
_pNode = _pNode->next;
return temp; // 由于temp为该函数体内部变量,所以返回时候只能按照值进行返回
}
self& operator--()
{
_pNode = _pNode->prev;
return* this;
}
self operator--(int)
{
self temp(*this);
_pNode = _pNode->prev;
return temp; // 由于temp为该函数体内部变量,所以返回时候只能按照值进行返回
}
/
/// 实现比较
bool operator==(const self& s)const
{
return _pNode == s._pNode;
}
bool operator!=(const self& s)const
{
return _pNode != s._pNode;
}
Node* _pNode;
};
list容器中的begin()、end()接口、以及迭代器的更名:
五、反向迭代器
由于反向迭代器的功能与正向迭代器几乎相似,有少部分的功能相反操作,所以在实现上直接以正向迭代器为模板,进行调用使用。
里面有一些注意点:
① 对于反向迭代器来说前置 rit++ 就相当于 正向迭代器 it--
对于俩个迭代器来++--符号位置不变正负号相反
② 注意解引用的位置
正向解引用直接把当前结点的值以引用的方式返回即可
而反向迭代器解引用需要需要进行一步后移操作
比如:进行rbgin()到rend()的打印,如果直接从rbegin()位置开始打印,就会直接打印根节点
③ 对于Ptr 和 Ref 因为是用正向迭代器作为模板,所以如果要使用就要到正向迭代器中去找
使用typedef Iterator::Ptr进行访问正向迭代器中的Ptr
④ 为了方便使用正向迭代器中的Iterator::Ptr ,给它取个别名Ptr
但是直接使用typedef进行取别名 编译器发生报错
因为静态成员变量在类外访问,也是通过类名+ : : (作用域限定符) +静态成员变量名来进行访
问,只有加上typename后,编译器才知道这里的typedef是给一个类型取别名,而不是操作
静态成员函数
template<class Iterator>
class Reverse_Iterator
{
typename typedef Iterator::Ptr Ptr;
typename typedef Iterator::Ref Ref;
typedef Reverse_Iterator<Iterator> self;
public:
Reverse_Iterator(Iterator it)
: _it(it)
{}
/
/// 解引用
Ptr operator*()
{
// return *_it; 不可以。因为对于反向迭代器来说从rbegin()位置开始,
// rbegin()为头结点位置,所以解引用应该
// 返回rbegin()的下一个结点即最后一个元素
Iterator temp(*this);
temp--;
return temp;
}
Ptr operator->()
{
return &(_it->pNode->_val);
}
/
/// ++ --
self& operator++()
{
--_it;
return *this;
}
self operator++(int)
{
_it--;
return *this;
}
self& operator--()
{
++_it;
return *this;
}
self operator--(int)
{
_it++;
return *this;
}
/
/// 比较
bool operator==(const self& s)const
{
return _it == s._it;
}
bool operator!=(const self& s)const
{
return _it != s._it;
}
Iterator _it;
};
六、list底层代码剖析
#include<iostream>
using namespace std;
namespace weige
{
template<class T>
struct ListNode
{
ListNode(const T& value = T())
: next(nullptr)
, prev(nullptr)
, val(value)
{}
ListNode* next;
ListNode* prev;
T val;
};
template<class T, class Ptr, class Ref>
class ListIterator
{
typedef ListNode<T> Node;
typedef ListIterator<T, Ptr, Ref> self;
public:
// 主要是给后序反向迭代器使用
typedef Ptr Ptr;
typedef Ref Ref;
public:
ListIterator(Node* pNode = nullptr)
: _pNode(pNode)
{}
/
/// 解引用
Ref operator*()
{
return _pNode->val;
}
Ptr operator->()
{
return &(_pNode->val);
}
/
/// ++ --
/*ListIterator<T, Ptr, Ref>& operator++()
{
_pNode = _pNode->next;
return*this;
}*/
self& operator++()
{
_pNode = _pNode->next;
return* this;
}
self operator++(int)
{
self temp(*this);
_pNode = _pNode->next;
return temp; // 由于temp为该函数体内部变量,所以返回时候只能按照值进行返回
}
self& operator--()
{
_pNode = _pNode->prev;
return* this;
}
self operator--(int)
{
self temp(*this);
_pNode = _pNode->prev;
return temp; // 由于temp为该函数体内部变量,所以返回时候只能按照值进行返回
}
/
/// 实现比较
bool operator==(const self& s)const
{
return _pNode == s._pNode;
}
bool operator!=(const self& s)const
{
return _pNode != s._pNode;
}
Node* _pNode;
};
template<class Iterator>
class Reverse_Iterator
{
typename typedef Iterator::Ptr Ptr;
typename typedef Iterator::Ref Ref;
typedef Reverse_Iterator<Iterator> self;
public:
Reverse_Iterator(Iterator it)
: _it(it)
{}
/
/// 解引用
Ref operator*()
{
// return *_it; 不可以因为对于反向迭代器来说从rbegin()位置开始,
// rbegin()为头结点位置,所以解引用应该返回rbegin()的下一个结点即最后一个元素
Iterator temp(_it);
--temp;
return *temp;
}
Ptr operator->()
{
return &(_it->pNode->_val);
}
/
/// ++ --
self& operator++()
{
--_it;
return *this;
}
self operator++(int)
{
_it--;
return *this;
}
self& operator--()
{
++_it;
return *this;
}
self operator--(int)
{
_it++;
return *this;
}
/
/// 比较
bool operator==(const self& s)const
{
return _it == s._it;
}
bool operator!=(const self& s)const
{
return _it != s._it;
}
Iterator _it;
};
template<class T>
class list
{
public:
typedef ListNode<T> Node;
typedef ListIterator<T, T*, T&> iterator;
typedef ListIterator<T, const T*, const T&> const_iterator;
typedef Reverse_Iterator<iterator> reverse_iterator;
typedef Reverse_Iterator<const_iterator> const_reverse_iterator;
/// 构造函数
list()
{
CreateHeadNode();
}
// 使用参数为int类型的n个值为value的元素进行构造
list(int n, const T& value = T())
{
CreateHeadNode();
for (int i = 0; i < n; ++i)
push_back(value);
}
template <class Iterator>
list(Iterator first, Iterator last)
{
CreateHeadNode();
while (first != last)
{
push_back(*first);
first++;
}
}
list(list& L)
{
CreateHeadNode();
for (auto e : L)
{
push_back(e);
}
}
list& operator=(const list L)
{
this->swap(L);
return *this;
}
/ 正向迭代器
iterator begin()
{
return iterator(_head->next);
}
iterator end()
{
return iterator(_head);
}
const_iterator begin()const
{
return iterator(_head->next);
}
const_iterator end()const
{
return iterator(_head);
}
/ 反向迭代器
reverse_iterator rbegin()
{
return reverse_iterator(end());
}
reverse_iterator rend()
{
return reverse_iterator(begin());
}
const_reverse_iterator rbegin()const
{
return reverse_iterator(end());
}
const_reverse_iterator rend()const
{
return reverse_iterator(begin());
}
/ 元素访问
T& front()
{
return _head->next->val;
}
const T& front()const
{
return _head->next->val;
}
T& back()
{
return _head->prev->val;
}
const T& back()const
{
return _head->prev->val;
}
/ 容量
bool empty()const
{
return _head == _head->next;
}
size_t size()const
{
Node* cur = _head->next;
size_t count = 0;
while (cur != _head)
{
count++;
cur = cur->next;
}
return count;
}
void resize(size_t newsize, const T& val = T())
{
size_t oldsize = size();
if (newsize < oldsize)
for (size_t i = newsize; i < oldsize; ++i)
pop_back();
else
for (size_t i = oldsize; i < newsize; ++i)
push_back(val);
}
/ 元素修改
void push_back(const T& val = T())
{
insert(end(), val);
}
void pop_back()
{
auto pos = end();
pos--;
erase(pos);
}
void push_front(const T& val = T())
{
insert(begin(), val);
}
void pop_front()
{
erase(begin());
}
iterator insert(iterator Itpos, const T& val = T())
{
Node* pos = Itpos._pNode;
Node* newNode = new Node(val);
newNode->next = pos;
newNode->prev = pos->prev;
newNode->prev->next = newNode;
pos->prev = newNode;
return pos->prev;
}
iterator erase(iterator Itpos)
{
Node* pos = Itpos._pNode;
if (pos == _head)
return pos;
pos->next->prev = pos->prev;
pos->prev->next = pos->next;
Node* ret = pos->next;
delete pos;
return ret;
}
void clear()
{
Node* cur = _head->next;
// 采用头删法
while (cur != _head)
{
_head->next = cur->next;
delete cur;
cur = _head->next;
}
_head->next = _head;
_head->prev = _head;
}
private:
void CreateHeadNode()
{
_head = new Node();
_head->next = _head;
_head->prev = _head;
}
private:
Node* _head;
};
}
void TestMylist1()
{
weige::list<int> L1;
weige::list<int> L2(10, 5);
int array[] = { 0,1,2,3,4,5,6,7 };
weige::list<int> L3(array, array + sizeof(array) / sizeof(array[0]));
weige::list<int> L4(L3);
}
void TestMylist2()
{
weige::list<int> L1;
L1.push_back(1);
L1.push_back(2);
L1.push_back(3);
L1.push_back(4);
L1.push_back(5);
L1.push_back(6);
L1.push_back(7);
L1.push_back(8);
L1.push_back(9);
cout << L1.size() << endl;
cout << L1.back() << endl;
cout << L1.front() << endl;
L1.erase(L1.begin());
// L1.erase(L1.begin(), L1.end());
cout << L1.size() << endl;
cout << L1.back() << endl;
cout << L1.front() << endl;
L1.clear();
cout << L1.size() << endl;
cout << L1.back() << endl;
cout << L1.front() << endl;
}
void TestMylist3()
{
weige::list<int> L1;
L1.push_back(1);
L1.push_back(2);
L1.push_back(3);
L1.push_back(4);
L1.push_back(5);
L1.push_back(6);
L1.push_back(7);
L1.push_back(8);
L1.push_back(9);
L1.resize(10, 10);
cout << L1.size() << endl;
cout << L1.back() << endl;
cout << L1.front() << endl;
L1.resize(5);
cout << L1.size() << endl;
cout << L1.back() << endl;
cout << L1.front() << endl;
}
void PrintList()
{
weige::list<int> L1;
L1.push_back(1);
L1.push_back(2);
L1.push_back(3);
L1.push_back(4);
L1.push_back(5);
L1.push_back(6);
L1.push_back(7);
L1.push_back(8);
L1.push_back(9);
L1.resize(10, 10);
auto it = L1.begin();
while (it != L1.end())
{
cout << *it << " ";
it++;
}
cout << endl;
}
void TestMyList4()
{
int array[] = { 0,1,2,3,4,5,6,7 };
weige::list<int> L(array, array + sizeof(array) / sizeof(array[0]));
auto it = L.begin();
while (it != L.end())
{
cout << *it << " ";
it++;
}
cout << endl;
auto rit = L.rbegin();
while (rit != L.rend())
{
cout << *rit << " ";
rit++;
}
cout << endl;
}
int main()
{
// TestMylist1();
// TestMylist2();
// TestMylist3();
// PrintList();
TestMyList4();
return 0;
}