Effective C 學習筆記(8)

2021-07-02 21:37:06 字數 1530 閱讀 7237

term11: handle assignment to self in operator =

1. 在=操作符內自我賦值有風險

我們可能不太會寫出類似a=a這樣的表示式。但如果說對於同乙個物件,其使用不同的指標、引用、容器等等指向它的時候,我們就很難保證一定不會自我賦值。自我賦值的實現裡,如果僅僅是類似於a.x=b.x這樣的賦值,可能除了浪費效能外並沒有太大的影響,真正的危險在於new、delete之類的操作。例如:

class bitmap;

class widget

bitmap* pb;

widget& widget::operator=(const widget& rhs)

delete pb;

pb = new bitmap(*rhs.pb);

return *this;

可以看出,如果rhs就是this指向的物件,那麼會出現pb指向的物件被銷毀,而賦值依然是這個被銷毀物件的位址。後續對這個物件的訪問勢必導致記憶體訪問錯誤。

下面介紹幾種處理方法。

2. 證同測試

就是檢測到自我賦值就直接退出而不做任何工作,如下:

widget& widget::operator=(const widget& rhs)

if(this == &rhs) return *this;

delete pb;

pb = new bitmap(*rhs.pb);

return *this;

} 這種方法迴避了自我賦值,但依然存在安全問題,如果pb = new bitmap(*rhs.pb);開闢新空間沒有成功,this->pb依然是無效的變數,訪問它會導致記憶體錯誤。

3. 語序順序控制

2中的**是先delete再new,所以new的結果無法影響delete。如果先new,new失敗了丟擲異常,沒有拋異常再delete,就可以避免這種情況。如下:

widget& widget::operator=(const widget& rhs)

bitmap* porig  = pb;

pb = new bitmap(*rhs.pb);

delete porig;

return *this;

} 4. copy and swap

這種方法要求實現形如void widget::swap(widget& rhs);的方法,將rhs與*this的成員互換。**如下:

widget& widget::operator=(const widget& rhs)

widget temp(rhs);

swap(rhs);

return *this;

}由於這裡呼叫了拷貝建構函式,可以將其簡化為:

widget& widget::operator=(const widget rhs)

swap(rhs);

return *this; }

這種方式將直接呼叫拷貝建構函式改為了隱式呼叫。上一段**由於是傳引用,因此需要顯式呼叫;而這裡由於是傳值,引數壓棧時會自動呼叫,**顯得更加精巧。當然,這種精巧使得**更晦澀,不見得是好事。

Effective C 學習筆記

學習effective c 已經有相當長的一段時間了,今天抽出時間又堵了一遍第一部分 c語言 c 以c語言為基礎,幾乎支援所有的c語言成分,例如區塊 語句 預處理 內建資料型別 陣列 指標等,c語言的侷限是 沒有模板 沒有異常 沒有過載 物件導向的c 也就是加上了物件特性的c,類 封裝 繼承 多型 ...

Effective C 學習筆記

1 c 是乙個複合式的語言 c 中不同部分有著不同的語言特性,例如 1.1 在c中傳遞形參時,按照值傳遞比按照指標傳遞效率更高 1.2 在物件導向程式中,物件要按照const引用而不是按照值傳遞 1.3 在stl程式設計中採取按照值傳遞方式 所以說c 中沒有統一的準則,要按照不同的特性採取不同的使用...

effective c 學習筆記

如果不考慮應用程式的使用場合,僅僅考慮語言的靈活性,我贊成作者的想法。但是不同的應用它會有不同的效能要求,所以語言的選擇,應該是用 最適合 條款去選擇。使用巨集定義常量,若定義在標頭檔案中,則所有包含標頭檔案的都可以使用。巨集定義,在預處理的時候進行替換。巨集定義一些簡單的函式,可以減少呼叫開銷,但...