C++深入學習:STL源碼剖析 (1) {STL、迭代器、前閉後開}

C++深入學習:STL源碼剖析 (1) {STL、迭代器、前閉後開}

STL六大組件
  1. 容器(containers):各種數據結構:如vector,map,list,deque,set等
  2. 算法(algorithm):各種常用算法:如sort,max,min,search,copy等
  3. 迭代器(iterators):扮演容器與算法的膠合劑,泛型指針
  4. 仿函數:實現角度可以認爲是重載了operator()的class
  5. 配接器:用來修飾容器或仿函數或迭代器接口
  6. 配置器:負責空間配置管理
前閉後開區間表示法 [)

任何一個STL算法都需要獲得一對迭代器所指示的區間,用來表示操作的範圍。C++ STL的迭代器所指示的空間都是前閉後開的,即 [first,end) ,也就是說實際範圍從first開始,直到end-1,迭代器end所指的是最後一個元素的下一個位置 ,通常find函數如果沒有找到則會返回end 。該off by one 的設計使得代碼變得乾淨利落

template <class InputIterator,class T>
InputIterator find(InputIterator first,InputIterator last,const T& value)
{
    while(first!=last && *first!=value)
        ++first;
    return first;
}
function call操作符重載

有時候我們希望對於一些函數,可以讓用戶指定某個條件或某個策略去執行,這些條件和策略背後便是一整組操作,一整組操作即需要函數。如sort函數可以用於一般情況(默認的遞增),也可以用於特殊情況(用戶自定義排序方式),但函數指針通常無法保持自己的 local states,達不到組件技術的可適配性,因此採用了仿函數。

template<class T> 
struct plus{   //將operator()重載,
    T operator() (const T& x,const T& y) const
    {
        return x+y;
    }
};
template<class T> 
struct minus{   //將operator()重載,
    T operator() (const T& x,const T& y) const
    {
        return x-y;
    }
};
cout<<plus<int>()(10,20)<<endl; //30
cout<<minus<int>()(20,10)<<endl; //10

//因此plus和minus就成爲了一個簡易的STL
迭代器Iterators

迭代器模式的核心思想:提供一種方法,使之能夠依序巡防某個容器所含的各個元素,又無需暴露該容器的內部表達方式。 滿足設計時將數據容器和算法分開獨立設計,最後通過迭代器這一膠着劑將二者撮合。

使用迭代器很大程度上隔離了容器的底層實現,只需要提供一個接口便可以對容器實現很多操作,例如簡單的find函數對鏈表、vector等實現也是不一樣的,但是通過迭代器便可以只需要寫一個迭代器版本即可,具體的遍歷細節由實現容器時的迭代器實現去完成。

迭代器就像一個指針,故迭代器最重要實現工作的就是要對 operator* 和 operator-> 重載。

C++ STL的迭代器所指示的空間都是前閉後開的,即 [first,end)

迭代器的用法:用迭代器遍歷vector<int>

    vector<int> arr{1,2,3,4,5};
    vector<int>::iterator it;
    for (it = arr.begin(); it != arr.end();it++)
    {
        cout << *it << ' ';
    }
   //1 2 3 4 5 

很顯然,從代碼中可知,每個容器都定義了自己的迭代器,並且定義了 ++ ,* 等操作,通常來說 *用來獲取迭代器當前位置的元素,++則是順着迭代器方向向下移動。

根據移動特性和實行操作,迭代器可以分爲5類

  1. Input iterator:不允許外界改變。只讀(read only) ,只能單步向前迭代
  2. Output iterator:不允許讀,只寫(write only),只能單步向前迭代
  3. Forward iterator: 可讀可寫,允許在該迭代器所指區間上進行讀取和寫入操作,單步向前迭代
  4. Bidirectional Iterator:可雙向移動,允許在該迭代器所指區間上進行讀取和寫入操作
  5. Random Access Iterator:可讀可寫,同時支持像指針一樣的操作,包括 p+n,p-n等
    在這裏插入圖片描述

一些使用迭代器遍歷和調用STL函數的例子:

    vector<int> arr{1,3,2,5,4};
    for_each(arr.begin(), arr.end(), [](int &a) { cout << a << ' '; });
	//1,3,2,5,4
	cout<<endl;
    sort(arr.begin(), arr.end());
    for(auto &i:arr)
        cout<<i<<' ';
	//1,2,3,4,5
容器的分類
序列式容器 關聯式容器
array set
vector map
heap multiset
priority_queue multimap
list hashtable
deque unordered_set
queue(配接器) unordered_map
stack(配接器)

序列式容器都是可序,不一定有序。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章