2011-10-22 51 views
2

我寫了下面的代碼:無法理解編譯器的行爲(創建對象)

#include <iostream> 

class A 
{ 
public: 
    A(){ std::cout << "created" << std::endl; } 
    A(A& other) { std::cout << "copied" << std::endl; } 
    A& get(){ std::cout <<"got" << std::endl; return *this; } 
    ~A(){ std::cout << "destroyed" << std::endl; } 
}; 

現在,線

A a = A().get(); 

A a;  
a = A(); 

編譯和正常工作,但

A a = A(); 

聲稱:

no matching function for call to ‘A::A(A)’ 
note: candidates are: A::A(A&) 
note:     A::A() 

使事情明確,

A a = (A&)A(); 

聲稱:

error: invalid cast of an rvalue expression of type ‘A’ to type ‘A&’ 

我完全不理解這種行爲。

P.S.我知道,如果我在複製c_tor中創建const引用,則一切都會好的。

回答

2
A a = A(); 

此行試圖調用傳遞一個臨時對象的copy-constructor,而copy-constructor通過非const引用接受參數。但是臨時對象不能綁定到非const引用。這就是你得到編譯錯誤的原因。

但是,臨時對象可以綁定到const引用。所以,解決的辦法是使參數const基準爲:

A(const A& other) { std::cout << "copied" << std::endl; } 
+1

這個解釋聽起來對我來說最合乎邏輯 – Lol4t0

3

複製構造函數應該將其參數作爲const引用(或簡單的A值)。在您當前的設置中,程序必須對臨時文件進行可變引用,這是無效的。

+0

你知道,g ++有時候並不這麼認爲。例如,'std :: auto_ptr '類型的私有成員將使g ++創建具有非const引用的默認副本c_tor – Lol4t0

+0

@ Lol4t0:可以使用非const引用的副本ctor;當您嘗試將其用於無法轉換爲非const引用的內容時(例如在此示例中),問題就會到來。 – Gorpik

3

這很簡單:右值(即的東西,必須在等號的右邊),可以轉換成一個恆定的參考或被複制。只有左值(即可以放在等號左邊的東西)可以轉換爲非常量參考。原因是你可能會試圖修改非常量引用的內容,這將是無效的。

A()是一個右值,因此不能轉換爲非常量引用。這是你的錯誤。

+0

好的,但爲什麼c_tor返回r值?我可以調用這個r值的成員,我甚至可以寫A()= A(); :)更多,爲什麼我的get()函數工作?如果你看看輸出,你可以看到,沒有任何對象被移除兩次 – Lol4t0

+0

哦,看起來也是,那個r值_can_be_ l值 – Lol4t0