为什么在这种情况下我的复制构造函数只被调用两次?
Why is my copy constructor only called twice in this scenario?
我有以下两个函数:
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
编译标志来抑制此优化,并查看当没有复制省略发生时编译器的行为。
- 从具有按值捕获的 lambda 移动构造 std::函数时,移动构造函数调用两次
- C++析构函数调用两次,堆栈分配的复合对象
- Qt插槽调用了两次
- 对于优化级别为 0 的 std::vector,析构函数被调用两次
- 为什么转换运算符调用复制构造函数两次,而等效函数只调用它一次
- 调用一个小函数两次(例如在if条件和主体中)比将结果存储在局部变量中更可取
- 为什么这个自定义分配器的析构函数在 GCC/MSVS 的 stdlib 中被调用两次
- 插槽调用了两次qt
- 调用某个回调函数两次会导致分段错误:Nan
- 基于 MFC 对话框的应用程序无法调用对话框两次
- 重载运算符 new(),为什么构造函数被调用两次?
- 当 reset() 被unique_ptr调用两次时会发生什么?
- 为什么在C 中超载邮政增量运算符两次调用构造函数
- 现代C++编译器是否能够避免在某些条件下两次调用常量函数
- 如果我对async_read进行两次调用,那么只有在处理完第一次调用之后,才会处理第二次调用,这是否安全
- 如何正确地将对象添加到向量,而无需两次调用析构函数
- boost::asio vs. libpcap:避免两次调用关闭
- 为什么 DNSServiceProcessResult 两次调用我的回调
- 在资源管理器左窗格上两次调用Windows 7外壳扩展dll Initialize方法
- 通过连续两次调用boost::asio::read来检索正确的数据