c ++中的复制构造函数中的const

时间:2011-11-14 16:02:01

标签: c++ copy copy-constructor

class x  
{  
    int a;  
public:  
    x()  
    {  
         cout<<"\n\ndefault constructor";  
    }  
    x(x& obj)  
    {  
         cout<<"\n\ncopy constructor";  
    }  
    x fun()  
   {  
      x ob;  
      return ob;  
    }  
};  
int main()  
{  
    x ob1;  
    x ob2=ob1.fun();  
    return 0;  
 }  

最初,这段代码给出了一个错误“没有匹配函数来调用'x :: x(x)'”, 当我将复制构造函数更改为

x(const x& obj)  
{  
    cout<<"\n\ncopy constructor";  
}  

输出变为

默认构造函数

默认构造函数
还是复制构造函数没有执行....为什么?

5 个答案:

答案 0 :(得分:14)

这称为由编译器完成的copy-elision,语言规范允许这样做。

请参阅此wiki条目:

至于为什么非const版本给出编译错误,因为obj1.fun()返回一个临时对象,它不能绑定到非const引用,但是它可以绑定到const引用,所以const版本编译得很好。一旦你使它成为const引用,它只用于语义检查,但编译器优化了代码,忽略了对copy-constructor的调用。

但是,如果使用GCC的-fno-elide-constructors选项编译它,则不会执行copy-elision,并且将调用copy-constructor。 GCC doc说,

  

<强> -fno-的Elid-构造

     

C ++标准允许实现省略创建临时文件,该临时文件仅用于初始化相同类型的另一个对象。 指定此选项会禁用该优化,并强制G ++在所有情况下都调用复制构造函数。

答案 1 :(得分:3)

编译器决定优化复制构造,因为它允许这样做,即使它通过const引用接受了参数。

答案 2 :(得分:1)

临时值是rvalues,不绑定到非常量引用。因此ob1.fun()无法绑定到x::x(x&)构造函数。

但是,rvalues 绑定到常量引用。

至于为什么没有输出:复制构造函数是标准中的一个特例,并且允许编译器忽略复制构造函数调用,即使复制构造函数有副作用。但是,施工必须仍然有效!另一个这样的例子是,如果你声明了复制构造函数explicit - 它仍然会被删除,但你的代码将是错误的。

在GCC中,你可以说-fno-elide-constructors带回你的构造函数。

答案 3 :(得分:1)

第一个错误是因为它试图将复制构造与临时对象一起使用。

ob1.fun();  // This returns an x by value

因此当你使用它时听到

x ob2=ob1.fun();       // You are passing it by value which requires a local temporary
// This is equivalent to this:
x  ob2(obj1.fun());    // So it is trying to do a copy construction.

Temporaries只能绑定到const引用。因此无法编译。

修复该问题后(使用临时问题)现在可以使用复制构造函数。但是如果可以的话,允许编译器优化它。它无法优化它,因为它甚至不允许在第一个版本中使用它。

答案 4 :(得分:1)

由于复制省略优化,您的副本构造函数调用被跳过。您不能依赖复制构造函数(如print语句)中的任何可观察行为。如果您确实希望看到它的输出,请尝试禁用优化。