準備實現gof上面乙個迭代器模式,用到了上面的list基本類,但是一直對賦值函式和拷貝建構函式不是很熟悉,就研讀了一下effective c++的關於這方面的一章,頗有收穫,抽取了我認為精華的部分分享給大家。由於一直對c++這一類的用法不是很熟悉,有錯誤或者優化或者需要特別強調的地方希望朋友們幫忙指出來,我再仔細分析改正。
故而例如乙個string類。
string a;
string b = a;//由於b還沒有被建立,故而呼叫的是拷貝建構函式。針對這種情況一般寫為string b(a);
string c;
b = c;//由於b已經被建立,呼叫的是賦值函式。
被賦值的物件存不存在是判斷呼叫的拷貝構造還是賦值函式的根本。
例如當乙個物件中有動態分配的記憶體的時候,或者簡單說來擁有乙個成員指標ptr。如果不加拷貝建構函式,而直接呼叫預設的拷貝建構函式的話,這樣執行的是物件的位拷貝,將兩個物件的位元流一模一樣,於是兩個物件分別有乙個指標ptr,它們指向實際上是同一塊記憶體區域。當呼叫析構函式釋放ptr的記憶體的時候,會被釋放兩次,這顯然是不合理的。
摘錄effective c++的原話:
解決這類指標混亂問題的方案在於,只要類裡有指標時,就要寫自己版本的拷貝建構函式和賦值操作符函式。在這些函式裡,你可以拷貝那些被指向的資料結構,從而使每個物件都有自己的拷貝;或者你可以採用某種引用計數機制(見條款 m29)去跟蹤當前有多少個物件指向某個資料結構。引用計數的方法更複雜,而且它要求建構函式和析構函式內部做更多的工作,但在某些(雖然不是所有)程式裡,它會大量節省記憶體並切實提高速度。
如果你真的很確信不需要拷貝構造和賦值的時候,可以只宣告這些函式(宣告為private成員)而不去定義(實現)它們。這就防止了會有人去呼叫它們,也防止了編譯器去生成它們。這樣在你試圖進行賦值或者copy的時候,編譯器會給你相應的錯誤資訊,避免你由於無意而進行這些操作
盡量使用成員初始化列表而不用建構函式賦值。物件的建立分兩步,首先是資料成員初始化,然後呼叫建構函式體。這樣如果類的物件成員的初始化在建構函式中的話,就會被初始化兩次,一次呼叫預設建構函式,一次呼叫賦值函式。如果在成員初始化列表中,就會僅僅呼叫一次拷貝建構函式來初始化。特別是const和引用資料成員只能用初始化,不能被賦值。「插一句關於const引用的總結:const引用只是表明不能通過此引用間接的改變被引用的物件,物件能不能被更改,取決於物件本身,僅僅是通過引用不可以更改,const放前放後沒有關係。"
摘錄的effective c++的原話:
養成盡可能使用成員初始化列表的習慣,不但可以滿足const和引用成員初始化的要求,還可以大大減少低效地初始化資料成員的機會。但有一種情況下,對類的資料成員用賦值比用初始化更合理。這就是當有大量的固定型別的資料成員要在每個建構函式裡以相同的方式初始化的時候。
manydatambrs::manydatambrs()
: a(1), b(1), c(1), d(1), e(1), f(1), g(1), h(1), i(0),
j(0), k(0), l(0), m(0)
manydatambrs::manydatambrs(const manydatambrs& x)
: a(1), b(1), c(1), d(1), e(1), f(1), g(1), h(1), i(0),
j(0), k(0), l(0), m(0)
寫乙個單獨的init函式,讓兩個函式都去呼叫情況似乎會更好一些。
void manydatambrs::init()
函式定義的寫法:
string& string::operator=(const string& rhs)
string::string(const string& rhs)
當定義自己的賦值運算子時,必須返回賦值運算子左邊引數的引用,*this。如果不這樣做,就會導致不能連續賦值,或導致呼叫時的隱式型別轉換不能進行,或兩種情況同時發生。
類裡有指標的時候,就要寫自己版本的拷貝構造和賦值函式。
如果確認不會有拷貝和賦值的情況,那就宣告這些函式為private型別,阻止編譯器生成預設的。
盡量採用成員初始化列表,少使用建構函式賦值。針對const和引用資料成員,必須採用初始化列表。
賦值函式,需要判定是否自己對自己賦值,如果是派生類需要呼叫基類的賦值函式,如果自己已經alloc了記憶體,需要首先釋放,然後賦值,最好返回*this.
拷貝建構函式可以通過呼叫賦值函式來實現構造操作。
C 拷貝建構函式和賦值函式
include using namespace std class string 建構函式 析構函式 賦值函式是每個類最基本的函式。每個類只有乙個析構函式和乙個賦值函式。但有很兩個建構函式,乙個為拷貝建構函式,其他為普通建構函式。對於乙個類,如果不編寫這四個函式,c 編譯器將自動為a產生四個預設函式...
拷貝建構函式和賦值建構函式
class cmystring 賦值建構函式 cmystring cmystring operator const cmystring str 新分配記憶體,將str的m pdata記憶體拷貝到m pdata中 m pdata new char strlen str.m pdata 1 strcpy...
拷貝建構函式和賦值建構函式
拷貝構造是確確實實構造乙個新的物件,並給新物件的私有成員賦上引數物件的私有成員的值,新構造的物件和引數物件位址是不一樣的,所以如果該類中有乙個私有成員是指向堆中某一塊記憶體,如果僅僅對該私有成員進行淺拷貝,那麼會出現多個指標指向堆中同一塊記憶體,這是會出現問題,如果那塊記憶體被釋放了,就會出現其他指...