2011-10-22 20 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