C++ 複製構造函數

——複製構造函數用於將一個對象的值複製到新建立的對象中,用於初始化過程當中(包括按值傳遞參數),而不是常規的賦值過程當中函數

原型:

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,這取決於具體的實現spa

  • 每當生成了對象副本時,編譯器都將使用複製構造函數。具體地說按值傳遞和返回對象時,都將調用複製構造函數(按值傳遞意味着建立原始變量的一個副本)。
  • 因爲按值傳遞對象時將調用複製構造函數,所以應該按引用傳遞對象。這樣能夠節省調用構造函數的時間以及存儲新對象的空間

功能:

——默認的複製構造函數逐個複製非靜態成員(成員複製也稱爲淺複製),複製的是成員的值指針

StringBad sailor = sports;

//等效於

StringBad sailor;
sailor.str = sports.str;
sailor.len = sports.len;

  只是因爲私有成員是沒法訪問的,所以後面的代碼不能經過編譯對象

靜態對象不受影響,由於它們屬於整個類,而不是各個對象blog

默認複製構造函數的問題:

一:

默認的複製構造函數不說明其行爲(全盤複製),若是須要在構造函數中修改類靜態數據成員,這時就會發生錯誤生命週期

解決辦法:提供一個顯示覆制構造函數內存

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初始化的指針成員,應當定義一個複製構造函數,以複製指向的數據,而不是指針,這被稱爲深度複製。複製的另外一種形式(成員複製或淺複製)只是複製指針值。淺複製僅淺淺地複製指針信息,而不會深刻「挖掘」以複製指針引用地結構

相關文章
相關標籤/搜索