2014-11-06 115 views
0

Iam試圖理解複製構造函數,請理解我是如何工作的。複製構造函數由用戶定義時的構造函數的行爲

案例1

class fruit{ 
    public: int i; 
      fruit(int j){ 
       i = j; 
      } 
}; 

int main(){ 
    fruit f1 = fruit(2); // works fine when no user defined copy constructor 
    return 0; 
} 

案例2

class fruit{ 
    public: int i; 
      fruit(fruit &f){ 
       i = f.i + 1; 
      } 
      fruit(int j){ 
       i = j; 
      } 
}; 

int main(){ 
    fruit f1 = fruit(2); // error no matching call fruit::fruit(fruit) why? 
    return 0; 
} 

案例3

class fruit{ 
    public: int i; 
      fruit(){ 
       i = 0; 
      } 
}; 

int main(){ 
    fruit f2; 
    fruit f1 = fruit(f2); // works fine when no user defined copy constructor 
    return 0; 
} 

案例4

class fruit{ 
    public: int i; 
      fruit(){ 
       i = 0; 
      } 
      fruit(fruit &f){ 
       i = f.i + 1; 
      } 
}; 

int main(){ 
    fruit f2; 
    fruit f1 = fruit(f2); // error no matching call fruit::fruit(fruit) 
    return 0; 
} 
Technically 'fruit(f2)' must be valid because 
f2 can be passed by reference to fruit(fruit &f). right? but why error? 

爲什麼我在Case 2Case 4得到錯誤?這是因爲我創建了用戶定義的拷貝構造函數嗎?如果原因是用戶定義的拷貝構造函數,則編譯器甚至會提供默認的拷貝構造函數。像內部fruit(fruit &)所以即使複製構造函數可用編譯器提供的程序。爲什麼它不會引起錯誤Case 1Case 3

我知道當用戶定義複製構造函數時,所有的構造函數都被阻止了==只能調用複製構造函數。但是一個類必須有一個拷貝構造函數可以由用戶或編譯器來完成。如果它是由編譯器提供的,那麼它也必須引發錯誤。但它不這樣做?

+0

'水果(水果)'是不是一個拷貝構造函數,只是一個普通的構造函數,需要一個左值'fruit'參考。 'fruit(fruit const&)'是一個拷貝構造函數,'fruit(fruit &&)'是一個移動構造函數,在你的例子中會被調用(如果提供的話)。這是因爲你構造的臨時值不是l值,所以不能綁定到l值引用('&'),但可以綁定到r值引用('&&')。 – Cameron 2014-11-06 18:31:34

+1

@Cameron:是的,這是一個複製構造函數。不如通常使用const引用,而是使用相同的拷貝構造函數。 – 2014-11-06 18:39:04

+0

@Cameron:不幸的是,它是一個拷貝構造函數。我不認爲它應該是,但是[C++ 11:12.8/2]不同意。 – 2014-11-06 18:41:36

回答

2

這不是專門與複製構造函數相關的問題;非const左值引用無法綁定到臨時對象。

下面的代碼會編譯:

fruit f1; 
fruit f2(f1); 

因爲f1不是臨時當你通過它

不過,你要的臨時工作,所以寫你的拷貝構造函數是這樣的:

fruit(const fruit& f) { 
    i = f.i + 1; 
} 

你的情況1和3分得手,因爲編譯器能夠產生自己的「默認」的拷貝構造函數^h看到你沒有提供一個,其中—不像你—它正確。 :-)

+0

你能解釋爲什麼案例2失敗? Iam傳遞整數爲什麼編譯器會檢查水果(fruit)? – user3205479 2014-11-06 18:50:45

+0

@ user3205479:你正在向'fruit(int)'傳遞一個整數,這可以正常工作......但是隨後你將生成的臨時對象複製到'f1'中,並且出於與其他情況相同的原因。如果你剛剛寫了'f1(2)水果',那麼它會起作用,因爲這不涉及複製任何水果。 – 2014-11-06 18:55:03

+0

它可能是暫時的,但爲什麼當有構造函數水果(int a)時它會檢查水果(水果)? – user3205479 2014-11-06 18:57:01

1
fruit f1 = fruit(f2); 

對於水果(f2),將創建不能綁定到非const引用的臨時對象。你必須使用follwoing副本constrcutor這個工作: -

fruit(const fruit& f) 
+0

我已經說過了。 – 2014-11-06 18:40:46

+0

你能解釋爲什麼案例2失敗? Iam傳遞整數爲什麼編譯器檢查水果(水果) – user3205479 2014-11-06 18:52:25

+0

在同一行水果(2)會導致暫時創建出默認的構造函數... – ravi 2014-11-06 18:57:47