2017-10-09 144 views
3
class A { 
public: 
    A() {} 
    A(const A& a) { cout << "A::A(A&)" << endl; } 
}; 

class B { 
public: 
    explicit B(A aa) {} 
}; 

int main() { 
    A a; 
    B b(a); 
    return 0; 
} 

爲什麼打印「A :: A(A &)」?C++爲什麼要調用複製構造函數?

何時調用「A」的複製構造函數?如果代碼調用複製構造函數,爲什麼我可以刪除複製構造函數而不會產生編譯錯誤?

回答

12

B(A aa)需要一個A通過值,所以當你執行B b(a)編譯器調用拷貝構造函數A(const A& a)生成名爲aa中的A實例explicit構造函數B

您可以刪除複製構造函數並使其仍然有效的原因是,如果您還沒有聲明移動構造函數,編譯器將爲您生成一個複製構造函數。

注意:編譯器生成的拷貝構造函數通常不足以滿足複雜的類,它執行簡單的成員智能拷貝,因此對於複雜元素或動態分配的內存,您應該聲明自己的。

§15.8.1

如果類定義不明確聲明拷貝構造函數,非明確的一個是隱式聲明。 如果類定義聲明移動構造函數或移動賦值運算符,則隱式聲明的複製 構造函數被定義爲已刪除;否則,它被定義爲默認(11.4)。如果 類具有用戶聲明的複製賦值運算符或用戶聲明的析構函數或賦值運算符,則不推薦使用後一種情況。

+0

編譯器生成的拷貝構造函數對於「複雜元素」應該沒有問題,如果所述元素是一種已被正確寫入的類型。 – juanchopanza

7

爲什麼拷貝發生

看看你class B c'tor:

class B { 
public: 
    explicit B(A aa) {} 
}; 

您可以通過獲得A,在通話過程中觸發副本。

如果你必須將其更改爲(通知A & aa):

class B { 
public: 
    explicit B(A & aa) {} 
}; 

世上本沒有任何副本...

默認的拷貝構造函數

當您刪除c'tor,編譯器會爲你生成一個這樣的代碼:

首先,你應該明白,如果你沒有聲明一個 的構造函數,編譯器會給你一個隱含的。隱含的 拷貝構造函數執行源對象的成員方式拷貝。

默認c'tor等同於:

MyClass::MyClass(const MyClass& other) : 
    x(other.x), c(other.c), s(other.s) {} 
相關問題