——復制建構式用于將一個物件的值復制到新創建的物件中,用于初始化程序中(包括按值傳遞引數),而不是常規的賦值程序中
原型:
Class_name(const Class_name &)
何時呼叫:
- 新建一個物件并將其初始化為同類現有物件時,復制建構式都將被呼叫
StringBad ditto(motto); // calls StringBad(const StringBad &) StringBad metoo = motto; // calls StringBad(const StringBad &) StringBad also = StringBad(motto); // calls StringBad(const StringBad &) StringBad * pStringBad = new StringBad(motto) // calls StringBad(const StringBad &)
中間兩種宣告可能會使用復制建構式直接創建metoo和also,也可能使用復制建構式生成一個臨時物件,然后將臨時物件的內容賦給metoo和also,這取決于具體的實作
- 每當生成了物件副本時,編譯器都將使用復制建構式,具體地說按值傳遞和回傳物件時,都將呼叫復制建構式(按值傳遞意味著創建原始變數的一個副本),
- 由于按值傳遞物件時將呼叫復制建構式,因此應該按參考傳遞物件,這樣可以節省呼叫建構式的時間以及存盤新物件的空間
功能:
——默認的復制建構式逐個復制非靜態成員(成員復制也稱為淺復制),復制的是成員的值
StringBad sailor = sports; //等效于 StringBad sailor; sailor.str = sports.str; sailor.len = sports.len;
只是由于私有成員是無法訪問的,因此后面的代碼不能通過編譯
靜態物件不受影響,因為它們屬于整個類,而不是各個物件
默認復制建構式的問題:
一:
默認的復制建構式不說明其行為(全盤復制),如果需要在建構式中修改類靜態資料成員,這時就會發生錯誤
解決辦法:提供一個顯示復制建構式
StringBad::StringBad(const String &s)
{
num_strings++; // static int num_strings宣告在類中
... // imported stuff to go here
}
如果類中包含這樣的靜態資料成員,即其值將在新物件被創建時發生變化,則應該提供一個顯示復制建構式
二:
隱式復制建構式的淺復制(復制指標)導致的記憶體問題
- 新物件可能修改指標指向的記憶體
- 新物件若走完生命周期將會呼叫解構式釋放指標指向的記憶體,但當原物件也呼叫解構式時,由于該段記憶體已被釋放,這將導致不確定的、可能有害的結果,另一個癥狀是試圖釋放記憶體兩次可能導致程式例外終止
解決辦法:定義一個顯示復制建構式,進行深度復制
StringBad::StringBad(const StringBad &st)
{
num_strings++; // handle static member update
len = st.len; // same length
str = new char [len + 1]; // allot space
std::strcpy(str, st.str); // copy string to new location
...
}
復制字串并將副本的地址賦給str成員
如果類中包含了使用new初始化的指標成員,應當定義一個復制建構式,以復制指向的資料,而不是指標,這被稱為深度復制,復制的另一種形式(成員復制或淺復制)只是復制指標值,淺復制僅淺淺地復制指標資訊,而不會深入“挖掘”以復制指標參考地結構
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/13771.html
標籤:C++
上一篇:C++ 靜態資料成員
下一篇:C++ 多載賦值運算子
