一步一步認識C STL中的迭代器

2021-06-22 11:27:55 字數 4112 閱讀 1106

一步一步認識c++stl中的迭代器「指標

」對所有

c/c++

的程式設計師來說,一點都不陌生。在接觸到

c語言中的

malloc

函式和c++

中的new

函式後,我們也知道這兩個函式返回的都是乙個指標,該指標指向我們所申請的乙個「堆

」。提到「堆

」,就不得不想到「棧

」,從c/c++

程式設計的角度思考,「堆

」和「棧

」最大的區別是「棧

」由系統自動分配並且自動**,而「堆

」則是由程式設計師手動申請,並且顯示釋放。如果程式設計師不顯示釋放「堆

」,便會造成記憶體洩漏,記憶體洩漏的危害大家知道,嚴重時會導致系統崩潰。

既然「指標」的使用者一不小心就可能導致記憶體洩漏,那麼我們如何能夠使得指標的使用變得更安全呢?從c++物件導向的角度分析,我們有沒有可能將「指標」封裝起來,使得使用者不直接接觸指標,而使用乙個封裝後的物件來替代指標的操作呢?

答案是顯然的,「智慧型指標」(smart pointer)正解決這類問題,尤其是在防止記憶體洩漏方面做得非常突出。c++標準庫std中提供了一種「智慧型指標類」名為"auto_ptr",先看下面的**:

void f()

正如上面的**所示,如果在兩條語句中間發生異常,會導致指標p所指的那塊記憶體洩漏,因為在執行delete之前發生異常,就不會自動釋放堆。然而,如果使用auto_ptr物件代替常規指標,將會自動釋放記憶體,因為編譯器能夠保證提前執行其析構函式。這樣,我們就可以將上述**改為:

#include//auto_ptr的標頭檔案

void f()

通過以上的分析,我們便對智慧型指標有了一定的了解。迭代器iterator就是一種智慧型指標,它對原始指標進行了封裝,並且提供一些等價於原始指標的操作,做到既方便又安全。

一提到stl,必須要馬上想到其主要的6個組成部件,分別是:容器、演算法、迭代器、仿函式、介面卡和空間分配器,本文主要介紹迭代器。迭代器是連線容器和演算法的一種重要橋梁。為什麼呢?我們舉個例子來說明原因。

#include#include//用到find函式

#includeusing namespace std;

int main()

if(vec.end()!=find(vec.begin(),vec.end(),7))

;class a1:public a{};//類a1繼承a

class b{};

void print(a)//只需指定引數型別

;//輸入迭代器

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{};//隨機訪問迭代器

//std::iterator,標準迭代器的類模板

templatestruct iterator//迭代器包含五個常用屬性

;//定義iterator_traits,用於提取迭代器的屬性,該類的物件不應該讓使用者看到

templatestruct iterator_traits

;//針對原始指標的偏特化版本

templatestruct iterator_traits;

//針對指向常用的原始指標設計的偏特化版本

templatestruct iterator_traits;

//定義兩個迭代器的差值型別的函式distance_type

templateinline typename iterator_traits::difference_type *

distance_type(const iterator&)

//獲取迭代器的value_type函式

templateinline typename iterator_traits::value_type *

value_type(const iterator&)

//求兩個一般迭代器之間的距離的函式_distance,供distance函式分類呼叫

templateinline typename iterator_traits::difference_type

_distance(inputiterator first,inputiterator last,input_iterator_tag)

return n;

}//求兩個隨機訪問迭代器之間的距離的函式_distance,供distance函式分類呼叫

templateinline typename iterator_traits::difference_type

_distance(randomaccessiterator first,randomaccessiterator last,

random_access_iterator_tag)

//自適應地呼叫distance函式

templateinline typename iterator_traits::difference_type

distance(inputiterator first,inputiterator last)

/*****下面的函式用於將指標移動n位的方法*/

//一般迭代器求向前移動的方法,與雙向迭代器和隨機反問迭代器不同

templateinline void _advance(inputiterator& i,distance n,input_iterator_tag)

}//針對雙向迭代器移動的方法

templateinline void _advance(bidirectionaliterator &iter,distance n,

bidirectional_iterator_tag)

} else//當n小於0時,向前移 }

}//定義隨機訪問迭代器移動的方法

templateinline void _advance(randomaccessiterator &iter,distance n,

random_access_iterator_tag)

//自適應的呼叫advance函式

templateinline void advance(inputiterator &iter,distance n)

從上面的**中不難發現,實現乙個迭代器,需要做一下工作:

1.定義5類迭代器的標誌類,該標誌類用於實現函式的區別呼叫(即過載),例如求兩迭代器距離函式distance(iter1,iter2,tag),移動函式advance(iter,n,tag)。這五個標誌類分別為:input_iterator_tag,output_iterator_tag,forward_iterator_tag,bidirectional_iterator_tag,random_access_iterator_tag。

2.對於每乙個iterator類,都必須包含5個屬性,分別為:iterator_category、value_type、difference_type、pointer、reference。

3.定義乙個迭代器的「屬性榨汁機」iterator_traits,用於獲取iterator的5中屬性值。

4.定義迭代器的操作,分別為:

1) 獲取iterator的標誌----->iterator_category(iter);

2)獲取兩迭代器差值的型別----->distance_type(iter);

3)獲取迭代器的原始型別--------->value_type(iter);

4)求兩迭代器的距離---------------->distance(iter1,iter2,tag);

5)將迭代器移動n位------------------>advance(iter,n,tag)。

[1]《c++ primer中文版 第4版》

[2]《stl原始碼剖析 侯捷》

一步一步 Sql Azure

一步一步 sql azure 1.使用 windowsazure 平台賬號登陸 2.新建sqlazure server 3.新建資料庫 4.為sql azure server 新增防火牆規則,只有將本機新增到規則裡才能從本機連線到該sqlazure server 5.連線到sql azure ser...

一步一步教你認識Python閉包

我在部落格中曾經介紹過兩篇關於函式的文章,第一篇是 關於 python 函式是第一類物件,第二篇是關於 lambda 函式,今天來說說 python 閉包。什麼是閉包?閉包有什麼用?為什麼要用閉包?今天我們就帶著這3個問題來一步一步認識閉包。閉包和函式緊密聯絡在一起,介紹閉包前有必要先介紹一些背景知...

一步一步教你認識 Python 閉包

我在部落格中曾經介紹過兩篇關於函式的文章,第一篇是 關於 python 函式是第一類物件,第二篇是關於 lambda 函式,今天來說說 python 閉包。什麼是閉包?閉包有什麼用?為什麼要用閉包?今天我們就帶著這3個問題來一步一步認識閉包。閉包和函式緊密聯絡在一起,介紹閉包前有必要先介紹一些背景知...