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