2015-09-03 49 views
3

我是新來的面向對象的編程,這可能是一個愚蠢的問題,但我不明白爲什麼使用A類代碼比B類更好,如果你想創建一個對象的副本。使用拷貝構造函數有什麼好處?

class A { 
    int num; 
public: 
    A(const A &ref) : num(ref.num) {}; 
}; 

class B { 
    int num; 
public: 
    B(B *ptToClass) : num(ptToClass->num) {}; 
}; 

如果我得到這個權利,拷貝構造函數是在A級使用

+0

http://stackoverflow.com/a/18611518/1012759它被標準禁止接受指針。 – CyberGuy

+3

@Cyber​​Guy這個問題說「複製對象」,而不是「創建複製構造函數」。您可以「複製對象」而無需複製構造函數。 – Yakk

+1

你確定A班比較好嗎?這兩個類看起來和我很相似,一個用無意義的拷貝構造函數,另一個用帶指針的隱含構造函數。 – anatolyg

回答

4

A類是靈活,安全:您從任何一個對象的副本你,即使是暫時的。

B類不太安全,因爲您可以使用nullptr調用構造函數。它的靈活性較低,因爲只能使用ypur構造函數來複制可以獲取地址的對象,而不是常量。

B b1(...);   
const B b2(...); 
B fb();  // function returning a B 

B b3(&b1);  
B b4(&b2);  // error b2 is const 
B b5(&fb()); // error you can't take adress of a temporary 
+0

關於B的第一點是真的,第二點不是的(因爲'B'有一個隱式定義的拷貝構造函數以及構造函數帶一個指針,所以它仍然可以被複制) –

+0

@JonathanWakely當然!對不起,我可憐的措辭:我的意思是提供給B的構造函數,而不是真正的拷貝構造函數。我編輯過。 – Christophe

0

它是由標準禁止在複製構造使用指針:

C++標準草案n3376 - 部分12.8.2:

類X A非模板構造器是一個拷貝構造函數,如果它的第一個參數的類型爲X &,const X &,volatile X &或const volatile X &,並且沒有其他參數ETERS否則所有其他 參數都有默認參數

Why is the argument of the copy constructor a reference rather than a pointer?

+2

但是B的構造函數不是複製構造函數,所以沒關係。 –

2

的事情是,如果一個構造函數被認爲是由編譯器拷貝構造函數,它是用特殊的方式使用。舉例來說,如果你有一個函數,通過複製把你的A類型的參數,如:

void function(A obj) { 
    // Do something with A 
    // ... 
} 

然後調用該函數:

int main() { 
    A a_obj; 
    function(a_obj); 
} 

function收到的目標obj會由您提供的複製構造函數創建。所以,爲您的類提供複製構造函數是件好事,這些複製構造函數將被複制,以便它們更好地適應語言功能和庫。

在您的應用程序中創建類型的構造函數沒有問題,如果這符合您的應用程序的需要,但編譯器不會將其理解爲複製構造函數,並且在編譯器或庫需要複製你的對象。

5

如果你沒有爲你的類聲明一個拷貝構造函數,那麼編譯器無論如何都會爲你聲明一個。類必須有複製構造函數。它們被烘焙成語言並具有特殊的地位。沒有它們,語言就無法運作。

可能最好的例子是在傳值時需要拷貝構造函數。當您按值傳遞時,編譯器將隱式調用複製構造函數。它不會打電話給構造函數B::B(B*)

所以,如果你想讓你的類是可複製的,你應該在複製構造函數中定義複製邏輯。這很簡單。

+0

「類**必須擁有複製構​​造函數。」不是真的。我不記得編譯器不會爲你發出拷貝構造函數的情況,但是從C++ 11開始,你可以顯式地刪除拷貝構造函數。 'std :: unique_ptr'沒有拷貝構造函數。 – lvella

+1

@Ivella它仍然**有一個副本構造函數,這很重要。如果你試圖複製一個'std :: unique_ptr',它將選擇拷貝的拷貝構造函數,然後你會收到一個錯誤,因爲它被刪除了。 – Brian

+1

我認爲「有」的定義在這裏有點過於... – lvella

相關問題