为什么我的复制构造函数在这种情况下只调用了两次?

时间:2013-05-12 11:58:59

标签: c++ pointers call-by-value

我有以下两个功能:

Class foo(Class arg)
{
    return arg;
}

Class bar(Class *arg)
{
    return *arg;
}

现在,当我单独调用foo(arg)时,复制构造函数当然会被调用两次。当我单独调用bar(& arg)时,它只调用一次。因此,我希望

foo(bar(&arg));

复制构造函数在这里被调用三次。但是,它仍然只被调用两次。这是为什么?编译器是否识别出不需要另一个副本?

提前致谢!

1 个答案:

答案 0 :(得分:6)

  

编译器是否识别出不需要另一个副本?

确实如此。编译器正在执行复制/移动省略。这是所谓的“as-if”规则的唯一例外,它允许编译器(在某些情况下,如你的例子中的那个)忽略对副本的调用或移动类的构造函数,即使它们有副作用效果。

根据C ++ 11标准的第12.8 / 31段:

  

当满足某些条件时,允许实现省略类的复制/移动构造   object,即使是为复制/移动操作选择的构造函数和/或对象的析构函数   有副作用。在这种情况下,实现处理省略的复制/移动的源和目标   操作只是指向同一对象的两种不同方式,以及对该对象的破坏   发生在两个对象在没有优化的情况下被销毁的时间的晚些时候。   复制/移动操作的省略,称为复制省略,在以下情况下是允许的(其中   可以合并以消除多个副本):

     

- 在具有类返回类型的函数的return语句中,当表达式是a的名称时   具有相同cv-unqualified的非易失性自动对象(函数或catch子句参数除外)   键入函数返回类型,可以通过构造省略复制/移动操作   自动对象直接进入函数的返回值

     

- [...]

     

- 当复制/移动尚未绑定到引用(12.2)的临时类对象时   对于具有相同cv-unqualified类型的类对象,可以省略复制/移动操作   将临时对象直接构造到省略的复制/移动

的目标中      

- [...]

使用GCC,您可以尝试使用-fno-elide-constructor编译标志来抑制此优化,并查看编译器在没有发生复制省略时的行为。