2017-10-05 113 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) {