困惑的語法
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);