1. 程式人生 > >advance()函式

advance()函式

目錄

一、 迭代器 

                                                            --------參考文獻   侯捷.STL原始碼剖析[M].武漢:華中科技大學出版社,2002.6:90-94.

一、 迭代器 

#include<cstddef>

template<typename T>
class iter
{
public:
	typedef iter iterator_category;		//自身型別
	typedef T value_type;		//相關型別
	typedef ptrdiff_t difference_type;		//距離 此處是int
	typedef T* pointer;		//指標型別
	typedef T& reference;	//引用型別
};

部分迭代器是用原生指標(pointer-to-const和pointer-to-non-const)實現的!

二、 型別萃取機 

型別萃取機是與迭代器配套使用的。

2.1 處理類實現的迭代器

template<class I>
struct iterator_traits
{
	typedef typename I::iterator_category iterator_category;
	typedef typename I::value_type value_type;
	typedef typename I::difference_type difference_type;
	typedef typename I::pointer  pointer;
	typedef typename I::reference reference;
};

2.2 處理原生指標實現的迭代器

部分迭代器使用原生指標(pointer-to-const和pointer-to-non-const)實現的,故而沒有類作用域,需要特殊處理: 

template<class T>
struct iterator_traits<T*>		//剔除指標型別
{
	typedef T* iterator_category;
	typedef T value_type;
	typedef ptrdiff_t difference_type;
	typedef T*  pointer;
	typedef T& reference;
};


template<class T>
struct iterator_traits<const T*>		//剔除指標型別以及const修飾
{
	typedef T* iterator_category;
	typedef T value_type;
	typedef ptrdiff_t difference_type;
	typedef T*  pointer;
	typedef T& reference;
};

三、 advance 

3.1 iterator_category

根據移動特性和行為,迭代器被分為5類:

  • Input Iterator:這種迭代器所指向的物件,不允許外界改變。只讀(read only)。
  • Output Iterator:只寫(write only)。
  • Forward Iterator:允許“寫入型”演算法(例如replace())在此種迭代器所形成的區間上進行讀寫操作。
  • Bidirectional Iterator:可雙向移動。某些演算法需要逆向走訪迭代器區間(例如逆向拷貝某範圍內的元素),可以使用Bidirectional Iterator。
  • Random Access Iterator:前四種迭代器都只供應一部分指標算術能力(前三種支援operator++,第四種再加上operator--),第五種則涵蓋所有指標算術能力,包括p+n, p-n, p[n], p1-p2, p1<p2。

3.2 啟用過載機制 

struct input_iterator_tag{ };
struct output_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{ };

下面羅列了四個同名過載函式,共同點就是都有三個引數且第三個引數都只宣告型別,併為指定引數名稱,因為它純粹是用來啟用過載機制,函式中根本不使用該引數(換句話說,如果要使用該引數,必須要有變數名)。如果硬要加上引數名稱也可以,畫蛇添足罷了。 

template<class InputIterator, class Distance>
inline void __advance(InputIterator& i, Distance n,			//前進
	input_iterator_tag)		//第三個引數是沒有引數名
{
	while (n--)++i;
}

template<class ForwardIterator, class Distance>
inline void __advance(ForwardIterator& i, Distance n,		//類似於有一個介面,本質還是前進
	forward_iterator_tag)
{
	__advance(i, n, input_iterator_tag());
}

template<class BidirectionalIterator, class Distance>
inline void __advance(BidirectionalIterator& i, Distance n,		//雙向
	bidirectional_iterator_tag)
{
	if (n >= 0)
		while (n--)++i;
	else
		while (n++)--i;
}

template<class RandomAccessIterator, class Distance>
inline void __advance(RandomAccessIterator& i, Distance n,
	random_access_iterator_tag)
{
	i += n;		//雙向,跳躍
}

3.3 實現advance函式

值得注意的是,到底是何種迭代器在編譯期就能確定下來,而不用等到執行時,以提高效率。

template<class InputIterator, class Distance>
inline void advance(InputIterator& i, Distance n)
{
	typedef iterator_traits<InputIterator>::iterator_category iterator_category;
	__advance(i, n, iterator_category());    //過載時,編譯器會自動去呼叫該呼叫的函式
}