STL list容器底层代码剖析、正向迭代器与反向迭代器的类的封装

目录

一、迭代器是什么

二、迭代器的本质

三、如何给一个容器实现迭代器功能

 四、正向迭代器功能的具体实现

 五、反向迭代器

 六、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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值