对于此计划
#include <iostream>
using std::cout;
struct C
{
C() { cout << "Default C called!\n"; }
C(const C &rhs) { cout << "CC called!\n"; }
};
const C f()
{
cout << "Entered f()!\n";
return C();
}
int main()
{
C a = f();
C b = a;
return 0;
}我得到的输出是:
Entered f()!
Default C called!
CC called!因为f()是按值返回的,所以它应该返回一个临时的。由于T a = x;是T a(x);,它不会调用复制构造函数来构造a,并将临时传入的参数作为其参数吗?
发布于 2010-02-24 10:19:58
由于
f()是按值返回的,因此它应该返回一个临时的。由于T a = x;是T a(x);,它不会调用复制构造函数来构造a,并将临时传入的参数作为其参数吗?
查找返回值优化。默认情况下,此选项处于启用状态。如果你是在Windows上使用MSVC 2005+,你可以使用/Od来关闭这个功能并获得想要的结果(或者在GCC上使用-fno-elide-constructors )。此外,有关MSVC的信息,请参阅this文章。
12.8复制类对象
15当满足某些条件时,允许实现忽略类对象的复制构造,即使对象的复制构造函数和/或析构函数有副作用。在这种情况下,实现将被省略的复制操作的源和目标简单地视为引用同一对象的两种不同方式,并且该对象的破坏发生在两个对象在没有优化的情况下将被销毁的较晚时间。115在以下情况下允许这种复制操作的省略(可以组合以消除多个副本):
-在具有类返回类型的函数中的返回语句中,当表达式是具有与函数返回类型相同的cv-类型的非易失性自动对象的名称时,可以通过将自动对象直接构造到函数的返回值中来省略复制操作。在抛出表达式中,当操作数是非易失性自动对象的名称时,可以通过将自动对象直接构造到异常对象中来省略从操作数到异常对象(15.1)的复制操作
-当未绑定到引用(12.2)的临时类对象将被复制到具有相同的cv未限定类型的类对象时,可以通过将临时对象直接构造到被省略的副本的目标中来省略复制操作
-当异常处理程序的异常声明(第15条)声明了与异常对象(15.1)相同类型的对象(cv限定除外)时,如果程序的含义除了执行异常声明声明的对象的构造函数和析构函数的执行之外保持不变,则可以通过将异常声明视为异常对象的别名来省略复制操作。
注意:重点是我的
发布于 2010-02-24 10:18:54
这是编译器支持的返回值优化(RVO)特性的一个示例。
当您按值返回时,复制构造函数可能不会被调用。
使用GCC上的-fno-elide-constructors选项关闭该功能。
发布于 2010-02-24 10:24:59
我相信它叫.
我假设当f()返回C对象时,该对象被分配在调用方法的堆栈空间中,因此初始化C a不需要复制。这是您的default C called。
C b = a这会导致一个复制构造函数,从而导致您的CC called。
顺便说一句,wiki上的示例看起来与您的代码非常相似。
https://stackoverflow.com/questions/2323225
复制相似问题