STL原始碼分析之copy演算法

2021-07-03 07:23:26 字數 3321 閱讀 8631

copy ----- 深入強化效率

首先,先看看assignment operator(即 operator =) 和拷貝建構函式的區別

第一,  他們是不可能被同時呼叫的

其次,不管什麼建構函式,它只可能在需要構造乙個物件的時候被呼叫,比如:

string s = s1;

string s(s1);

這裡呼叫的是拷貝建構函式,是構造新物件用的

而過載的operator=,完全可以看成乙個一般的成員函式。我們也知道在物件還沒有構造出來之前,討論非靜態的成員函式時沒有意義的,所以operator= 必然是發生在物件生成之後,一次新的賦值

string s;             //預設建構函式

s = s1; //呼叫operator = ,因為此時s已經被構造出來了

關於copy

函式,我們討論的是

operator=

為了提高效率,stl演算法用盡辦法,包括函式過載,型別特性,偏特化等。

要注意的是,copy函式的賦值操作可能是向前推進的,即從給定第乙個位置開始賦值,不斷累加,直到最後。說是可能,是因為函式還可能因為效率問題呼叫memcpy或是memmove等底層函式。

根據copy函式的賦值進行順序,函式的結果可能是會出錯的。

如果輸入區間和輸出區間完全沒有重疊,當然毫無問題; 否則如果輸出區間的終點在輸入區間裡面,根據copy的賦值順序,是不會出現問題的

然而如果輸出區間的起點在輸入區間裡面,那麼因為copy的賦值順序可能就會造成錯誤,說是可能,是因為函式可能因為效率而呼叫memmove等函式,這類函式會事先將區間內容複製下來,所以是不會造成錯誤的

現在我們來看看copy的源**實現細節:

templateinline outputiterator copy(inputiteratorfirst, inputiterator last, outputiterator result )

下面是過載函式,針對原生指標,我們可以視為特殊的迭代器

iinlne char *copy(const char *first, constchar *last, char *result)

iinlne wchar_t *copy(const wchar_t *first,const wchar_t *last, wchar_t *result)

可見,對於普通的char*, wchar* 這種型別的形參型別,都是直接呼叫的memmove底層函式,對於未知型別的型別則予以更複雜的處理。    

關於memmove,這裡給乙個簡單的解釋:

void * memmove(void *dest, const void *src,size_t count)

函式用於從src拷貝count個位元組到dest;

如果目標區域和源區域有重疊的話,此函式能保證源串在被覆蓋之前將重疊區域的位元組拷貝到目標區域中,複製後的src也會被更改

如果目標區域與源區域沒有重疊,則類似memcpy

copy的泛化版本中呼叫的__copy_dispatch函式 ,此函式有乙個完全泛化版本和兩個偏特化版本:(注意的是都使用了仿函式)

先看看完全泛化版本:

templatestruct __copy_dispatch

};

再看看兩個偏特化版本:

//版本1,倆引數都是t*指標形式

templatestruct __copy_dispatch};

//版本2,第乙個引數為constt*指標形式,第二個引數為t*形式

templatestruct __copy_dispatch

}

走到這裡,我們發現,已經分成了兩路,一路是根據使用的迭代器,通過型別來挑選不同的演算法;一路是根據使用的原生指標,通過判斷是否有重要的賦值函式來挑選不同的演算法。

首先,我們走第一條路看看

這裡是在使用迭代器的情況下,對不同型別迭代器的不同操作:

//對於使用的是inputiterator迭代器的容器:

template inline outputiterator__copy(inputiterator first, inputiterator last,

outputiteratorresult, input_iterator_tag)

//對於使用randomaccessiterator迭代器的容器

template inline outputiterator

__copy(randomaccessiteratorfirst, randomaccessiterator last,

outputiterator result,random_access_iterator_tag)

template inline outputiterator

__copy_d(randomaccessiteratorfirst, randomaccessiterator last,

outputiterator result, distance*)

接著,我們來走第二條路

這裡是在使用原生指標的情況下,判斷是否有重要的賦值函式

template inline t* __copy_t(const t* first, const t* last, t* result,__true_type) 

template inline t* __copy_t(const t* first, const t* last, t* result,__false_type)

以上就是所有關於copy的內容了,如果要真的消化這裡面的內容,需要對語言的不斷認識!

STL演算法分析之Copy()演算法

在看sgi stl原始碼的時候,畢竟會碰到很多的演算法,不理解這些演算法對我們的閱讀產生了很大的影響,現在先來分析下幾個已經碰到的了的演算法。第乙個copy 演算法。copy演算法說起來很簡單就是將迭代器裡面的 first,last 區間裡的元素賦值到指定的 result 指定的區間裡面去 resu...

STL原始碼分析之power演算法

關於演算法power 一般我們遇到要實現power演算法,最直接就是如下實現 cpp view plain copy print?int power int x,unsigned int n 然而,這樣計算的複雜度為o n 想要改進,因為 x n x n 2 x n 2 所以我們想,只要計算出了x ...

STL原始碼分析之Vector

地球人都知道vector的查詢效率很高,插入和刪除的效率低下,容器會隨著元素的不斷增加自動增長,最近在看了stl原始碼之後,發現確實是這樣,下面是vector一些關鍵的函式.從這些函式可以看出插入和刪除的過程,以及容器自動增長的方式.兩個通過下標獲取元素的函式.reference operator ...