【STL源碼剖析】令人困惑的語法

困惑的語法

obj * volatile * my_free_list的含義

這個聲明原來的形式是:obj** my_free_list,這樣的話*my_free_list(空閒的內存塊指針數組中的一個元素)可能被優化到寄存器中,從而使庫代碼無法lock住對它的讀調用(如果在寄存器中則另一個線程可能會無意中修改該寄存器的值,而在內存中由於另一個線程沒有訪問權力所以不能修改)。
要聲明變量必須在內存中就要用volatile修飾,這裏修飾的是my_free_list,是free_list數組中的一個元素,而不是數組指針,所以volatile放在兩個中間。

刻意製造臨時對象

刻意製造臨時對象。如string(“hello”);int(2);中的hello、2都是一個無名的臨時對象。

靜態常量整數成員在class內部直接初始化

class類中的const static integral data member,可以在類中直接賦初值。這是C++標準,integral泛指所有整型(char,long…)

宏定義

define __STL_TEMPLAE_NULL template<>

在GCC,VC6中允許不指定template<>就可以完成指定特定類型

define __STL_NULL_TMPL_ARGS <>

這種申明爲了實現bound friend templates,也就是說,模板類的某個實現與友元類的某個實現一一對應。比如,操作符重載。
詳見P33

需要注意的地方

T1 *pt1 = new(p) T1(value)

T1 *pt1 = new(p) T1(value)這叫placement new,在指針p(p是T1類型)所指向的內存空間創建一個類型爲T1的對象。當然,構造的這個對象需要顯示調用它的析構函數:pt1->~T1(),而不能用delete來完成。見more Effective C++ M8

set_new_handle(0)

set_new_handle(0)的意思是operator new申請一塊內存失敗時返回0,STL自己處理內存不足情況。
set_new_handle()的原型是:

typedef void (*new_handler)(); //定義返回值爲空,參數爲空的函數指針。
new_handler set_new_handler(new_handler p) throw();//operator new申請一塊內存失敗時調用p所指向的函數。並返回一個新的處理函數。

當operator new無法滿足內存分配需求時,它會不斷調用由set_new_handle()返回的new_handler函數,直到找到足夠的內存。因此,應該妥善設計new_handler函數,一個設計良好的new_handler函數必須做以下事情:
1、刪除其它無用的內存,使系統具有可以更多的內存可以使用,爲下一步的內存申請作準備。
實現此策略的辦法是:程序一開始執行就分配一大塊內存,當new_handler被調用時,將它們釋放還給程序使用。

2、設置另外一個new_handler。
如果當前的new_handler不能夠做到更多的內存申請操作,或者它知道另外一個new_handler可以做到,則可以調用set_new_handler函數設置另外一個new_handler,這樣在operator new下一次調用的時候,可以使用這個新的new_handler。

3、卸載new_handler,使operator new在下一次調用的時候,因爲new_handler爲空拋出內存申請異常。

4、new_handler拋出自定義的異常

5、不再返回,調用abort或者exit退出程序

ptrdiff_t

兩個指針相減的結果的類型爲ptrdiff_t,它是一種有符號整數類型。減法運算的值爲兩個指針在內存中的距離(以數組元素的長度爲單位,而非字節),因爲減法運算的結果將除以數組元素類型的長度。所以該結果與數組中存儲的元素的類型無關。

size_t是unsigned類型,用於指明數組長度或下標,它必須是一個正數,std::size_t.設計size_t就是爲了適應多個平臺,其引入增強了程序在不同平臺上的可移植性。

ptrdiff_t是signed類型,用於存放同一數組中兩個指針之間的差距,它可以使負數,std::ptrdiff_t.同上,使用ptrdiff_t來得到獨立於平臺的地址差值.

size_type是unsigned類型,表示容器中元素長度或者下標,vector::size_type i = 0;

difference_type是signed類型,表示迭代器差距,vector:: difference_type = iter1-iter2.前二者位於標準類庫std內,後二者專爲STL對象所擁有。

操作符重載p38

int& operator*()const
{
return (int&)m_i
}

(int&)m_i它告訴編譯器,你確實要將const int轉爲non-const lvalue。
這樣方便對象作爲左值。如果不明確的轉換可能會報警告或錯誤。

迭代器是前閉後開區間表示[ )

所謂前閉後開[first,last),就是說整個範圍從first開始,知道last-1結束。這樣使得算法的循環設計乾淨利落。

for(;first != last; ++first) {//...}

function call 操作符( operator() )

如果你針對某個class進行operator()重載,它就會成爲一個仿函數。可以代表函數指針,也可以代表一整組操作。

template<class T>
struct plus{
T operator()(const T& x,const T& y) const{return x + y;}
};

上面就是一個最簡單的仿函數,它還不具備配給能力。
但是可以這樣用了:

plus<int> plusobj;
int a = plusobj(2,3);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章