我有以下两个函数:
Class foo(Class arg)
{
return arg;
}
Class bar(Class *arg)
{
return *arg;
}
现在,当我单独调用foo(arg)时,复制构造函数当然会被调用两次。当我单独调用bar(&arg)时,它只被调用一次。因此,我期望
foo(bar(&arg));
复制构造函数在这里被调用了三次。然而,它仍然只被调用两次。为什么呢?编译器是否认识到不需要另一个副本?
提前感谢!
编译器是否识别出不需要另一个副本?
确实如此。编译器正在执行复制/移动省略。这是所谓的"as-if"规则的唯一例外,它允许编译器(在某些情况下,如您的示例中的情况)忽略对类的复制或移动构造函数的调用,即使这些调用有副作用。
c++ 11标准第12.8/31段:
当满足某些条件时,允许实现省略类的复制/移动构造object, ,即使为复制/移动操作选择了构造函数和/或对象的析构函数有副作用。在这种情况下,实现处理省略的复制/移动的源和目标操作就是引用同一对象的两种不同方式,以及该对象的销毁发生在时间的后期,如果没有优化,两个对象就会被破坏。这种对复制/移动操作的省略,称为copy省略,在以下情况下是允许的可以组合以消除多个副本):
—在具有类返回类型的函数的
return
语句中,当表达式是a的名称时具有相同cv-不合格的非易失性自动对象(函数或catch子句参数除外)类型作为函数返回类型,则可以通过构造来省略复制/移动操作自动对象直接转化为函数的返回值— [...]
-没有绑定到引用(12.2)的临时类对象将被复制/移动对于具有相同cv- undefined类型的类对象,可以通过将临时对象直接构造为省略的copy/move
的目标— [...]
对于GCC,您可以尝试使用-fno-elide-constructor
编译标志来抑制此优化,并查看当没有复制省略发生时编译器的行为。