More Effective C 讀書筆記(二)

2022-06-23 07:06:11 字數 2189 閱讀 8009

1、不要試圖過載||,&&操作符,因為它們使用短路求值法(一旦確定了布林表示式的真假值,即使還有部分表示式沒有被測試,布林表示式也停止運算),而過載之後採用的是函式呼叫法。首先當函式被呼叫時,需要運算其所有引數,所以呼叫函式functions operator&& 和 operator||時,兩個引數都需要計算,換言之,沒有採用短路計算法。第二是c++語言規範沒有定義函式引數的計算順序,所以沒有辦法知道表示式1與表示式2哪乙個先計算。完全可能與具有從左引數到右引數計算順序的短路計算法相反。同樣,也不要試圖過載逗號(,)操作符,因為乙個包含逗號的表示式首先計算逗號左邊的表示式,然後計算逗號右邊的表示式,整個表示式的結果是逗號右邊表示式的值,這也可能和函式呼叫法對引數的計算順序不同。因為過載操作符很重要的一點就是要過載之後行為特性與其被料想(預設的行為特徵)的一樣。否則,過載是完全輕率的行為。c++規定不能過載的操作符有., .*, ::, ?:,new, delete, sizeof, typeid,static_cast, dynamic_cast, const_cast, reinterpret_cast

2、理解各種不同含義的new和delete(new操作符和operator new操作),先分析一段**:

string *ps = new string("memory management");

使用的new是new操作符。這個操作符就象sizeof一樣是語言內建的,你不能改變它的含義,它的功能總是一樣的。

它要完成的功能分成兩部分:第一部分是分配足夠的記憶體以便容納所需型別的物件。第二部分是它呼叫建構函式初始化記憶體中的物件。new操作符總是做這兩件事情,你不能以任何方式改變它的行為(不能過載)。

完成new操作符功能的第一部分分配記憶體所呼叫函式的名字是operator new(可以過載)。

函式operator new 通常這樣宣告:

void * operator new(size_t size);

返回值型別是void*,因為這個函式返回乙個未經處理(raw)的指標,未初始化的記憶體。引數size_t確定分配多少記憶體。你能增加額外的引數過載函式operator new,但是第乙個引數型別必須是size_t。operator new的職責只是分配記憶體(返回乙個void *指標,有點類似c語言的malloc)。它對建構函式一無所知。

當你的編譯器遇見這樣的語句:

string *ps = new string("memory management");

它生成的**或多或少與下面的**(偽碼)相似:

void *memory = operator new(sizeof(string)); // 得到未經處理的記憶體

call string::string("memory management") on *memory;// 為string物件初始化

string *ps = static_cast(memory); //記憶體中的物件是ps指標指向新的物件

同樣,我們分析定位new操作符,例如:

new (buffer) widget(widgetsize)

當該定位new操作符隱含呼叫operator new函式時,把這個變數(記憶體位址buffer)傳遞給它。被呼叫的operator new函式除了待有強制的引數size_t外,還必須接受void*指標引數,指向構造物件占用的記憶體空間。這個operator new就是placement new,它看上去象這樣:

void * operator new(size_t, void *location)

總結:如果想在堆上建立乙個物件,應該用new操作符。它既分配記憶體又為物件呼叫建構函式。如果你僅僅想分配記憶體,就應該呼叫operator new函式;它不會呼叫建構函式。如果你想定製自己的在堆物件被建立時的記憶體分配過程,你應該寫你自己的operator new函式,然後使用new操作符,new操作符會呼叫你定製的operator new。如果你想在一塊已經獲得指標的記憶體裡建立乙個物件,應該用placement new。

對於delete和operator delete也有類似的結論:

delete 先呼叫析構函式,然後呼叫operator delete釋放記憶體,而operator delete僅僅是釋放記憶體。如果你用placement new在記憶體中建立物件,你應該避免在該記憶體中用delete操作符。因為delete操作符呼叫operator delete來釋放記憶體,但是包含物件的記憶體最初不是被operator new分配的,placement new只是返回轉遞給它的指標。誰知道這個指標來自何方?而你應該顯式呼叫物件的析構函式來解除建構函式的影響。

More Effective C 《基礎議題》

1 指標 指標是乙個變數,只不過這個變數儲存的是乙個位址,指向記憶體的乙個儲存單元 而引用跟原來的變數實質上是同乙個東西,只不過是原變數的乙個別名而已。如 int a 1 int p a int a 1 int b a 上面定義了乙個整形變數和乙個指標變數p,該指標變數指向a的儲存單元,即p的值是a...

More Effective C 擴充套件方法

c 3.0中增加了許多新特性.其中.擴充套件方法允許我們在不修改原有 的基礎上擴充套件類 介面的功能.有技巧的運用該特性.能寫出有效率 易維護 美觀的 c 2.0提供了許多泛型與容器的介面和類.最常見的如icomparable常常需要新建乙個comparable來進行排序比較等等.但其預設只有乙個c...

more effective C 條款四解讀

深刻考慮是否需要給類提供乙個預設建構函式 有一些類擁有乙個預設建構函式是合理的需求,比如string比如容器 linked list vector 預設建構函式可以把他們初始化為空容器。但是有一些類我們最好還是不要提供預設建構函式。比如乙個equipment類 class equipment 對於這...