2017-10-05 163 views
-1
#include <iostream> 

using namespace std; 

class Test { 
public: 
    Test() { 
     cout << "Default constructor called." << endl; 
    } 
    Test(Test &obj) { 
     cout << "copy constructor called." << endl; 
    } 
    Test& operator=(const Test &obj) { 
     cout << "copy assignment called." << endl; 
     return *this; 
    } 
    ~Test() { 
     cout << "destructor called." << endl; 
    } 
}; 

Test func(Test test) { 
    cout << "func called" << endl; 
    return test; 
} 

int main(int argc, char* argv[]) { 
    Test t1; 
    Test t2 = func(t1); // No matching constructor for initialization for 'Test' 
    return 0; 
} 

我正在學習C++。我寫了一些測試代碼來了解複製初始化和複製分配。現在我無法弄清楚爲什麼第二項任務不能工作。複製初始化不起作用?

+6

拷貝構造函數簽名是錯誤的,應該是'測試(const的測試和OBJ)'不'測試(測試和OBJ)' – Galik

+0

編譯器會告訴你響亮而明確:「類型的非const引用無效初始化'測試&'「。所以,使你的拷貝構造函數的參數成爲一個const引用(這是正常的情況),它將起作用。 – Rene

+0

@Galik謝謝你,它現在有用! –

回答

2

rvalue無法修改,在這種情況下,應該將其視爲常量引用const Test& obj。所以當你將t1轉換爲func中的test時,這是可以的,因爲t1是一個左值,但不是從返回值構造t2時,這是一個xvalue(分類爲右值)。

總之,你的拷貝構造函數的簽名是錯誤的,因爲它只接受左值。

第10行的以下補丁使代碼對我有用。

Test(const Test &obj) { 
    ^~~~~ 

這是關於cppreference.com上copy constructor的文章。請參閱語法部分。
另外,rvalue製品,其讀取

右邊的值可以被用於初始化一個const左值參考,在這種情況下,由右值標識的對象的壽命延長到參考端部的範圍。



附:你也可以使用移動語義(C++ 11),它只接受右值。寫這樣的移動構造函數並不難:

Test(Test&& obj) ... 
+0

允許複製構造函數修改源對象,並且不必接受const引用。 –

+0

@ M.M突然意識到出了什麼問題。修正了。 – iBug

1

您的副本構造函數允許修改被複制的對象。

聲明

Test t2 = func(t1); 

會的func()的返回值存儲在一個臨時的,然後複製到t2。但是,這需要一個接受const引用的拷貝構造函數,因爲臨時文件不能綁定到非const引用。 (從技術上講,編譯器允許臨時刪除,但仍然需要爲您的代碼發出診斷信息,假設它已經創建了臨時文件,換句話說,複製構造函數必須爲const)。

更改複製構造函數以接受const參考。

Test(Test const &obj) {