2017-10-16 158 views
2

有些東西我無法理解。看看這樣的主:C++瞭解複製構造函數

class C { 
public: 
    C() { cout << "C0 "; } 
    C(const C&) { cout << "Cc"; } 
}; 

class D { 
public: 
    C c; 
    D() { cout << "D0 "; } 
    D(const D&) { cout << "Dd"; } 
}; 

int main() { 

    D x; cout << endl; 
    D y(x); cout << endl; 
    return 0; 

} 

//output is: 
C0 D0 
C0 Dd 

我同意的事實,D xC0 D0作爲輸出,因爲d類存在於C默認構造函數的調用,然後創建對象D

D y(x)就像D y = x其中(像以前一樣)C被創建(所以輸出C0)和複製構造函數被調用。爲什麼不出現Cc?如果你考慮這個代碼:

class C { 
public: 
    C() { cout << "C0 "; } 
    C(const C&) { cout << "Cc"; } 
}; 

class D { 
public: 
    C c; 
    D() { cout << "D0 "; } 
}; 

int main() { 

    D x; cout << endl; 
    D y(x); cout << endl; 
    return 0; 

} 

//output is: 
C0 D0 
Cc 

爲什麼現在輸出是Cc

的代碼是,除了一個事實,即沒有對D的拷貝構造函數話說D y(x)就像D y = x我期望像以前一樣創建(調用默認的構造函數,以便輸出C0)是c的定義相同然後沒有文字,因爲D(const D&)而不是定義。

也許我誤解了複製構造函數。他們在這種情況下叫什麼名字?

+0

你在找什麼是[「隱含聲明的拷貝構造函數」](http://en.cppreference.com/w/cpp/language/copy_constructor#Implicitly-declared_copy_constructor) –

+0

@DrewDormann正是那個;) –

回答

3

而且D y(x)就像D y = x

它不喜歡它,正是它。後者只是第一個語法糖。

其中(像以前一樣)C創建(所以輸出C0)和拷貝構造函數被調用

沒有,C拷貝構造函數是不是在這種情況下調用。您沒有定義您的D拷貝構造函數來調用C拷貝構造函數,所以c成員是默認構造的,這就是您看到C0的原因,但由於您實際上沒有拷貝c,所以您看不到Cc

您所期待的D拷貝構造函數來自動通話D的成員的拷貝構造函數,但是這根本就不是這樣。你必須明確地定義這種行爲自己,如:

D(const D &src) : c(src.c) { } 

爲什麼不Cc出現?

因爲您的C拷貝構造函數根本沒有在您的D y(x)示例中調用。

+0

完美清晰的答案,我現在明白了。 –

+0

一個無意義的問題。我已經仔細閱讀了你寫的內容,並且我自己意識到了答案(並且對視覺工作室的測試證實了它)。再次感謝 –

6

在第一種情況下,您的D Copy構造函數需要顯式調用C複製構造函數。

D(const D &d) : c(d.c) 
{ cout << "Dd"; } 

在第二種情況下,由於您沒有定義D copy-ctor,編譯器會爲您生成一個。

爲了使這更清晰,增加了額外的int於C和D.

static int counter; 
class C { 
public: 
    int index; 
    C() { index = ++counter; cout << "C0 "; } 
    C(const C&) { index = c.counter; cout << "Cc"; } 
}; 

class D { 
public: 
    int dcounter; 
    C c; 
    D() { dcounter = ++counter; cout << "D0 "; } 
    D(const D&) : dcounter(D.dcounter) 
{ cout << "Dd"; } 
}; 

現在,調試步驟直通,或添加更多printfs輸出()。 當您執行D y(x)時,您會看到y中的成員c不是從任何東西中拷貝的 - 只是構造而已。

+0

你是正確的。 Sombody編輯了我的答案,並將其放在operator =()的部分。我現在刪除了。 – joeking

3

當你定義一個自定義的拷貝構造函數時,它會做你告訴它的事情;你不會告訴它複製c成員,所以它不會,因此C0。事實上,如果你的價值在於c,你會發現它甚至在新複製的成員中都沒有。

如果您沒有自定義副本構造函數,則被調用的默認副本構造函數會爲其複製的成員調用複製構造函數。在這種情況下,您會在複製的實例中看到最終值。

+0

謝謝。所以在第一種情況下,我的D(const D&),因爲我沒有告訴他做一個副本,它沒有複製項目。正確?我以爲複製是在默認情況下完成的,我沒有寫它 –

+1

這是正確的,你沒有告訴'D'複製構造函數複製'c',所以它沒有。您必須在成員初始化列表中自己調用成員拷貝構造函數。 –