當我們顯式或者隱式地對該型別進行拷貝操作時,就會用到該類的拷貝建構函式(copy construction)和拷貝賦值操作符(
copy-assignment operator)。
如果乙個建構函式的第乙個引數是自身類型別的引用,且任何額外引數都有預設值,則此建構函式是拷貝建構函式。
拷貝建構函式的詳細介紹請參見另外兩篇文章。
類拷貝賦值操作符就是」=」,該操作符用於將乙個類的物件賦值給類的另乙個物件。如下**所示:
myclass a, b;
a = b;
如果沒有定義類的拷貝建構函式和拷貝賦值操作符,則c++編譯器會自動為該類進行定義,這就是預設的拷貝建構函式與拷貝賦值操作符。
預設的拷貝建構函式會將其引數的成員逐個拷貝到正在建立的物件中。假設有乙個自定義類
class person
那麼該類的預設拷貝建構函式的定義為
person(const std::string& name, int age) : name(name), age(age)
預設的拷拷貝賦值操作符會將其引數的成員逐個賦值給正在建立物件的成員。以「3.1
預設的拷貝建構函式」中提到的
person
類為例,則其預設的拷貝賦值操作符的定義為
person& operator=(const person& that)
name = that.name;
age = that.age;
return *this;
當自定義的類要處理資源的時候,就需要對其拷貝建構函式與拷貝賦值操作符進行自定義。在「3.1
預設的拷貝建構函式」中提到的
person
類的進行修改:
class person
此時person
類的成員變數
name
的型別改為
char*
。則此時
person
類的建構函式定義為
person(const char* the_name, int the_age)
在其建構函式中,使用了new
關鍵字分配了記憶體空間,即
person
類涉及到了「管理資源」。則此時的析構函式中就要對其分配的記憶體空間進行釋放
~person()
}
如果此時使用person
類的預設的拷貝建構函式與拷貝賦值操作符,則其預設建構函式的定義為
person(char* name, int age) : name(name), age(age)
需要注意的時,此時預設拷貝建構函式中的name(name)
只是將name
的值即指標值進行了拷貝,並沒有拷貝指標指向的字串。以如下**為例
person a("yang", 20);
person b(a);
此時,a.name
與b.name
的關係如圖所示
因為a.name和
b.name
指向同一塊記憶體,當
b結束其生命週期時呼叫其析構函式,此時即使
a還在其生命週期內,其
a.name
指向的記憶體已經被銷毀。
person a("yang", 20);
if (a.m_age > 10)
printf("a.name = %s", a.m_name);
以上**中,printf
無法列印出
a.name
的值。從上面的分析可知,預設拷貝建構函式並沒有分配新的記憶體資源從而導致錯誤的產生。因此,在自定義拷貝建構函式中,要分配新的記憶體,並且將內容拷貝到新的記憶體空間中。
person(const person& that)
此時,a.name
與b.name
的關係如圖所示
當b結束其生命週期時呼叫其析構函式,釋放其所占用的記憶體空間,對
a的值沒有影響。
自定義拷貝賦值操作符與自定義拷貝建構函式類似,也要重新分配記憶體空間。
person& operator=(const person& that)
}
自定義拷貝賦值操作符與自定義拷貝建構函式的不同之處在於,定義拷貝建構函式是建立乙個新的物件,而自定義拷貝賦值操作符是更新乙個已有的物件。所以,在自定義拷貝賦值操作符中,需要釋放掉已占有的資源,之後在分配新的資源,將名字拷貝到新的資源中。在自定義拷貝賦值操作符中也要檢查是否是「自賦值(
self-assignment
)」。「自賦值」指的是拷貝複製操作符的兩端的運算元是同乙個數,即自己給自己賦值。這樣的話,在釋放了之前的資源後,就沒辦法賦新值了,所以必須保證拷貝賦值操作不是「自賦值」。
拷貝建構函式與賦值操作
class char n nsize n private char 類的物件中包含指標,指向動態分配的記憶體資源 int一 拷貝建構函式 intclass 拷貝建構函式 void char n nsize n private char 類的物件中包含指標,指向動態分配的記憶體資源 int 複製常規成...
C 賦值函式與拷貝建構函式
一看到 操作符,認為必然呼叫賦值函式,然而在下面的例子中,語句a b c顯示的是呼叫拷貝建構函式。結論 在看到 操作符為物件賦值的時候,如果是在物件的定義時候出現則呼叫拷貝建構函式,如果是不是,例子中的b d,則為賦值函式。include using namespace std class a a ...
C 拷貝建構函式與賦值函式
c 拷貝建構函式與賦值函式 c 的拷貝函式和賦值函式既有聯絡又有區別,不細究的話很容易搞混,遂以小例示之如下,權作解惑之用 test.cpp include include include using namespace std class book book const book book boo...