STL-迭代器

1.迭代器

1.1正向迭代器

正向迭代器是用一个类封装的,迭代器类。例如:在vector,string中的迭代器就相当于一个指针,在list类中用一个类来封装一个节点,实质上也还是一个指针,迭代器就相当于指向一个节点的指针。

现在以list为例子,list的迭代器,代码如下:

//迭代器类
// 一个链表指针用迭代器封装,实质上还是一个指针
//迭代器也就相当于指向一个节点的指针
//第一种解决const类型的迭代器
//const迭代器类
template<class T>
struct ListConstIterator
{
	typedef ListNode<T> Node;
	typedef ListIterator<T> Self;

	Node* _node; //一个迭代器节点

	//迭代器构造
	ListConstIterator(Node* node) :_node(node)
	{}

	++it
	前置++,返回++以后的值
	Self& operator++()
	{
		_node = _node->_next;
		return *this;
	}

	it++
	后置++
	Self operator++(int)
	{
		Self tmp(*this);//浅拷贝,即两个迭代器指针指向同一个空间,直接应用默认拷贝构造
		_node = _node->_next;
		return tmp;//拷贝
	}

	--it
	Self& operator--()
	{
		//向前走
		_node = _node->_prev;
		return *this;
	}

	it--
	Self operator--(int)
	{
		Self tmp(*this);
		_node = _node->_prev;
		return tmp;
	}

	*it
	解引用,返回的是数据
	T& operator*()
	{
		return _node->data;
	}

	==
	比较两个迭代器相等,即比较迭代器的位置(引用/地址)相同
	bool operator==(const Self& it)
	{
		return _node == it._node;
	}

	//!=
	bool operator!=(const Self& it)
	{
		return _node != it._node;
	}

	//->
	//返回的是数据的地址
	T* operator->()
	{
		return &_node->data;
	}
};

1.3 正向const迭代器

const迭代器和普通迭代器区别是: const迭代器指向的内容不能被修改!即为const_iterator begin() const,相当于const int *p
而迭代器器本身不能修改是const iterator begin(),也就相当于int * const p
所以普通迭代器和const迭代器的代码差异只在解引用是有差别
第一种解决方法是在普通迭代器的基础上再写一个const迭代器类,代码如下:

普通迭代器:

//const迭代器类
template<class T>
struct ListConstIterator
{
	typedef ListNode<T> Node;
	typedef ListIterator<T> Self;

	Node* _node; //一个迭代器节点

	//迭代器构造
	ListConstIterator(Node* node) :_node(node)
	{}

	++it
	前置++,返回++以后的值
	Self& operator++()
	{
		_node = _node->_next;
		return *this;
	}

	it++
	后置++
	Self operator++(int)
	{
		Self tmp(*this);//浅拷贝,即两个迭代器指针指向同一个空间,直接应用默认拷贝构造
		_node = _node->_next;
		return tmp;//拷贝
	}

	--it
	Self& operator--()
	{
		//向前走
		_node = _node->_prev;
		return *this;
	}

	it--
	Self operator--(int)
	{
		Self tmp(*this);
		_node = _node->_prev;
		return tmp;
	}

	*it
	解引用,返回的是数据
	T& operator*()
	{
		return _node->data;
	}

	==
	比较两个迭代器相等,即比较迭代器的位置(引用/地址)相同
	bool operator==(const Self& it)
	{
		return _node == it._node;
	}

	//!=
	bool operator!=(const Self& it)
	{
		return _node != it._node;
	}

	//->
	//返回的是数据的地址
	T* operator->()
	{
		return &_node->data;
	}
};

const迭代器

//第一种解决const类型的迭代器
//const迭代器类
template<class T>
struct ListConstIterator
{
	typedef ListNode<T> Node;
	typedef ListConstIterator<T> Self;

	Node* _node; //一个迭代器节点

	//迭代器构造
	ListConstIterator(Node* node) :_node(node)
	{}

	++it
	前置++,返回++以后的值
	Self& operator++()
	{
		_node = _node->_next;
		return *this;
	}

	it++
	后置++
	Self operator++(int)
	{
		Self tmp(*this);//浅拷贝,即两个迭代器指针指向同一个空间,直接应用默认拷贝构造
		_node = _node->_next;
		return tmp;//拷贝
	}

	--it
	Self& operator--()
	{
		//向前走
		_node = _node->_prev;
		return *this;
	}

	it--
	Self operator--(int)
	{
		Self tmp(*this);
		_node = _node->_prev;
		return tmp;
	}

	*it
	解引用,返回的是数据
	const T& operator*()
	{
		return _node->data;
	}

	==
	比较两个迭代器相等,即比较迭代器的位置(引用/地址)相同
	bool operator==(const Self& it)
	{
		return _node == it._node;
	}

	//!=
	bool operator!=(const Self& it)
	{
		return _node != it._node;
	}

	//->
	//返回的是数据的地址
	const T* operator->()
	{
		return &_node->data;
	}

};

第二种解决方法:由于const迭代器和普通迭代器只有解引用重载的返回值不一样

//普通迭代器
解引用,返回的是数据
	T& operator*()
	{
		return _node->data;
	}

	//->
	//返回的是数据的地址
	T* operator->()
	{
		return &_node->data;
	}
//const迭代器
解引用,返回的是数据
	const T& operator*()
	{
		return _node->data;
	}
	
	//->
	//返回的是数据的地址
	const T* operator->()
	{
		return &_node->data;
	}

由于两个代码差别不大,只是重载的返回值不一样。第一种也会导致代码冗余,所以用模板来解决以下的问题,代码如下:

template<class T,class Ref,class Ptr>
struct ListIterator
{
	typedef ListNode<T> Node;
	typedef ListIterator<T,Ref,Ptr> Self;

	Node* _node; //一个迭代器节点

	//迭代器构造
	ListIterator(Node *node):_node(node)
	{}

	++it
	前置++,返回++以后的值
	Self& operator++()
	{
		_node = _node->_next;
		return *this;
	}

	it++
	后置++
	Self operator++(int)
	{
		Self tmp(*this);//浅拷贝,即两个迭代器指针指向同一个空间,直接应用默认拷贝构造
		_node = _node->_next;
		return tmp;//拷贝
	}

	--it
	Self& operator--()
	{
		//向前走
		_node = _node->_prev;
		return *this;
	}

	it--
	Self operator--(int)
	{
		Self tmp(*this);
		_node = _node->_prev;
		return tmp;
	}

	*it
	解引用,返回的是数据
	//T& operator*()
	Ref operator*()
	{
		return _node->data;
	}

	==
	比较两个迭代器相等,即比较迭代器的位置(引用/地址)相同
	bool operator==(const Self& it)
	{
		return _node == it._node;
	}

	//!=
	bool operator!=(const Self& it)
	{
		return _node != it._node;
	}

	//->
	//返回的是数据的地址
	//T* operator->()
	Ptr operator->()
	{
		return &_node->data;
	}
};


template<class T>
class list
{
public:
	//重定义节点类名
	typedef ListNode<T> Node;
private:
	Node* _head;//哨兵位
	size_t _size;//链表中节点的个数

public:
	......
	//第二种方法解决const迭代器类
	typedef ListIterator<T,T&,T*> iterator;
	typedef ListIterator<T,const T&,const T*> const_iterator;
	
	//迭代器的引用
	iterator begin()
	{
		//iterator it(_head->_next);//有名对象
		//return it;
		return iterator(_head->_next);//这是应用的是一个匿名对象
	}

	iterator end()
	{
		return iterator(_head);
	}

	//const迭代器,需要迭代器不能修改,还是迭代器指向的内容?
	// 迭代器指向的内容不嫩被修改! const iterator不是我们需要的const迭代器
	//以下是迭代器本身不能修改
	//const iterator begin()错误
	const_iterator begin() const
	{
		//iterator it(_head->_next);//有名对象
		//return it;
		return const_iterator(_head->_next);//这是应用的是一个匿名对象
	}

	const_iterator end() const
	{
		return const_iterator(_head);
	}
};

1.3反向迭代器和反向const迭代器

在我们主观意识上,正向迭代器的begin指向的是除去哨兵位的第一个节点,end则是指向最后一个节点下一个节点(即哨兵位头节点)。而我们也会觉得rbegin则是指向最后一个数据,rend指向第一个节点的上一个节点(即哨兵位头节点),如图
反向迭代器

但是,在c++库中我们则见到的是将begin和rend指向的第一个节点,end和rbegin都指向哨兵位头节点,如图
C++库中的反向迭代器
但是库中的解引用时,会是先++,再解引用

//解引用
Ref operator*()
{
	//return *_it;
	//解引用的是前一个
	Iterator tmp = _it;
	return *(--tmp);
}
#include<iostream>
#include<vector>
#include<string>
using namespace std;

//所有容器的反向迭代器
//迭代器适配器

	//给我vector<T>::iterator,list<int>::iterator
	//适配出相应的反向迭代器
	//本来,每个容器都要写一个反向迭代器的类,但是自己写,太费劲了
	template<class Iterator, class Ref, class Ptr>
	struct ReverseIterator
	{
		typedef ReverseIterator<Iterator, Ref, Ptr> Self;//重命名

		Iterator _it;
		//构造
		//反向迭代器封装一个正向迭代器
		ReverseIterator(Iterator it) :_it(it)
		{}

		Ref operator*()
		{
			//return *_it;
			//解引用的是前一个
			Iterator tmp = _it;
			return *(--tmp);
		}

		Ptr operator->()
		{
			//return _it.operator->();
			return &(operator*());
		}

		//++调用迭代器中的--
		Self& operator++()
		{
			--_it;
			return *this;
		}

		Self& operator--()
		{
			++_it;
			return *this;
		}

		bool operator!=(const Self& s)
		{
			return _it != s._it;
		}
	};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值