迭代器辅助函数

c++标准程序提供了三个辅助函数,分别是advance(), distance(),iter_swap();通过这三个辅助函数可以增强迭代器的能力,比如 list 也具备了向前跳跃 n个元素的能力了。

Advance()

advance()可以将迭代器的位置为增加,增加的幅度由参数决定,即使迭代器一次性前进或后退多个元素。
函数声明如下:
void advance(InputIterator &pos, Dist n);
1.对Bidirectional 迭代器 和Random Access迭代器而言, n可以为负值,表示向后跳跃。
2.Dist 是个template型别,通常应该是个整数型别。
3.advance()并不检查迭代器是否超过序列的end(),所以存在一个潜在的危险:如果对序列尾端执行"operator++"操作将会导致未定义的操作行为。

需要特别说明的是,此函数总能根据迭代器类型(category)采用最佳方案,这个归于迭代器特征(iterator traits)的应用。面对Random Access迭代器,此函数只是简单的执行 pos += n。对于其他的类型的迭代器则执行 ++pos n次,后文再介绍iterator traits。
/****************************************************************
*函数名称:AdvanceInstance
*功    能:advance函数使用示范
*作    者:Jin
*日    期:2016年5月29日
****************************************************************/
void AdvanceInstance()
{
	typedef list<int> IntList;
	IntList Collector;
	//insert 0 1 2 3 4 5 6 7 8 9
	for (int i = 0; i < 10; i++)
	{
		Collector.push_back(i);
	}

	IntList::iterator pos = Collector.begin();

	//output: 0
	cout << "fist element: " << *pos << endl;

	//step three element forward 
	advance(pos, 3);
	//output: 3
	cout << "step three element forward: " << *pos << endl;
	
	advance(pos, -2);
	//output: 1
	cout << "step two element backward: " << *pos << endl;
}

Distance()

函数distance用来处理两个迭代器之间的距离,函数声明如下:
Dist distance(_InIt _First, _InIt _Last);
1.传回两个input迭代器_First,_Last之间的距离。
2.两个迭代器都必须是指向同一个迭代器。
3.如果不是Random Access迭代器,则_Last迭代器必须和_First相同或在_First之后,否则会导致未定义行为
4.返回值的Dist型别由迭代器决定:iterator_traits<InputIterator>::difference_type

advance函数类似,此函数能根据迭代器类型(category)采用最佳方案,以达到最佳的性能。对于Random Access迭代器该函数传回_Last -_First的值,对于其他迭代器类型需要不断递增_First 直到抵达_Last 。、
/****************************************************************
*函数名称:DistanceInstance
*功    能:distance函数应用举例
*作    者:Jin
*日    期:2016年5月29日
****************************************************************/
void DistanceInstance()
{
	typedef list<int> IntList;
	IntList Collector;
	//insert -3 -2 -1 0 1 2 3 4 5 6 7 8 9
	for (int i = -3; i <= 9; i++)
	{
		Collector.push_back(i);
	}

	//search element with value 5
	IntList::iterator pos;
	pos = find(Collector.begin(), Collector.end(), 5);
	if (pos != Collector.end())
	{
		cout << "difference between beginning and element with value 5: "
			 << distance(Collector.begin(), pos) << endl;
	} 
	else
	{
		cout << "can not find element with value 5" << endl;
	}

}

Iter_swap ()

该函数是用来交换两个迭代器所指的元素值,函数原型如下:
void iter_swap(_FwdIt1 pos1, _FwdIt2 pos2);
1.迭代器的型别可以不同,但是其所指的两个值必须是可交换的。
/****************************************************************
*函数名称:IterSwapInstance
*功    能:iter_swap()函数应用示例
*作    者:Jin
*日    期:2016年5月29日
****************************************************************/
void IterSwapInstance()
{

	typedef vector<int> IntVector;
	IntVector coll;
	for (int i = 1; i <= 9; ++i)
	{
		coll.push_back(i);
	}
	
	//output:1 2 3 4 5 6 7 8 9
	PrintElements(coll,"list1:");

	//output:2 1 3 4 5 6 7 8 9 
	iter_swap(coll.begin(), ++coll.begin());
	PrintElements(coll, "list2:");
	
	//output:9 1 3 4 5 6 7 8 2 
	iter_swap(coll.begin(), --coll.end());
	PrintElements(coll, "list3:");
}

迭代器特性

在distance()函数,advance()函数中均提到,这个两个函数能根据迭代器类型采用最佳的实作方案,以达到最加的性能要求。其实现原理:通过迭代器标志(tags)和特性(traits, 由<iterator>提供),将操作行为重载得以实现。

STL为每一种迭代器提供了一个迭代器标志(iterator tag),用来作为迭代器的标签(label):
namespace std 
{
	struct output_iterator_tag 
	{

	};
	struct input_iterator_tag
	{

	};

	struct forward_iterator_tag : public input_iterator_tag
	{

	};

	struct bidirectional_iterator_tag : public forward_iterator_tag
	{

	};
	struct random_access_iterator_tag : public bidirectional_iterator_tag
	{

	};
}
如果编写泛型程序代码,我们还需要了解迭代器所指元素的型别。STL提供了一种特殊的template结构来定义迭代器特性(iterator traits),该结构包含了迭代器相关的所有信息,为“迭代器应具备的所有型别定义(包括迭代器类型,元素型别等)”提供一致接口:
namespace std
{
	template <class T>
	struct iterator_traits 
	{
		//定义迭代器所指的元素类型
		typedef typename T::value_type value_type;
		//定义两个迭代器距离
		typedef typename T::difference_type difference_type;
		//定义迭代器类型
		typedef typename T::iterator_category iterator_category;
		//定义指针
		typedef typename T::pointer pointer;
		//定义引用
		typedef typename T::reference reference;
	};
}
在这个template中,T代表迭代器型别,有了它,就可以编写任何运用“迭代器类型”等特征的泛型程序代码了,例如:
typedef vector<int> IntVector;
IntVector coll;
for (int i = 1; i <= 9; ++i)
{
	coll.push_back(i);
}
iterator_traits<IntVector::iterator>::value_type temp(*coll.begin());
这个“迭代器特性”结构有两个优点:
1、能够确保每一个迭代器所提供必要的型别定义。
2、能够针对特性的迭代器进行特化

上述第二条,运用于”一般指针作“时有:
namespace std
{
	template <class T>
	struct iterator_traits<T*> 
	{
		typedef T value_type;
		//定义距离
		typedef ptrdiff_t difference_type;
		//定义迭代器类型
		typedef random_access_iterator_tag iterator_category;
		//定义指针
		typedef T* pointer;
		//定义引用
		typedef T& reference;
	};
}

运用迭代器类型(iterator_categories)

如果希望针对不同的迭代器类型采用不同的实作方案(采用函数重载技术),需要按照下面两步来进行:
1.将迭代器类型作为template函数的附件参数。
2.针对不同的迭代器类型实作出上述所调用的函数

现在以迭代器辅助函数distance()为例介绍其调用过程,辅助函数advance()实现方法和distance()一样。
template<class Iterator>
typename std::iterator_traits<Iterator>::difference_type
distance (Iterator pos1, Iterator pos2)
{
	return distance(pos1, pos2, 
				    std::iterator_traits<Iterator>::iterator_category);
}

//distance for random access iterator
template<class Raiterator>
typename std::iterator_traits<Raiterator>::difference_type
distance(Raiterator pos1, Raiterator pos2, std::random_access_iterator_tag)
{
	return pos2 - pos1;
}

//distance for input, forward, and bidirectional iterator
template<class Initerator>
typename std::iterator_traits<Initerator>::difference_type
distance(Initerator pos1, Initerator pos2, std::input_iterator_tag)
{
	typename std::iterator_traits<Initerator>::difference_type d;
	for (d = 0; pos1 != pos2; ++pos1, ++d)
	{
		;
	}
	return d;
}

原文地址:https://www.cnblogs.com/jinxiang1224/p/8468412.html