C ++复制构造函数,临时函数和复制语义

时间:2010-02-24 02:15:11

标签: c++ variable-assignment copy-constructor compiler-optimization temporaries

对于这个程序

#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,并将临时传入作为其参数?

3 个答案:

答案 0 :(得分:14)

  

由于f()按值返回,因此应返回临时值。由于T a = x;T a(x);,它是否会调用复制构造函数来构造a,并将临时传入作为其参数?

查找返回值优化。这是默认打开的。如果您使用的是MSVC 2005+,则可以使用/Od将其关闭并获得所需的结果(或GCC上的-fno-elide-constructors)。此外,对于MSVC,请参阅this文章。

  

12.8复制类对象

     

15 当满足某些条件时,a   允许实现省略   复制类对象的构造,   即使是复制构造函数和/或   对象的析构函数有侧面   效果。在这种情况下,   实现对待源和   省略的复制操作的目标   仅仅是两种不同的方式   指的是同一个对象,而且   该对象的破坏发生在   两个时代的晚些时候   对象会有   没有了就被摧毁了   优化.15这种复制的省略   允许操作   以下情况(可能是   结合消除多重   副本):

     

- 在a的return语句中   具有类返回类型的函数   当表达式是a的名称时   用非易失性自动对象   同样的cv-unqualified类型   函数返回类型,副本   操作可以省略   构造自动对象   直接进入函数的返回   值    - 在一个throw-expression中,何时   操作数是a的名称   非易失性自动对象,   从操作数复制操作到   异常对象(15.1)可以省略   通过构造自动对象   直接进入异常对象

     

-   当一个临时的类对象有   没有受到参考(12.2)   将被复制到一个类对象   相同的cv-unqualified类型,副本   操作可以省略   构造临时对象   直接进入了目标   省略副本

     

- 什么时候   例外的异常声明   handler(第15条)声明一个对象   相同类型(除了   cv-qualification)作为例外   对象(15.1),复制操作即可   通过治疗来省略   exception-declaration作为别名   异常对象,如果的含义   该计划将保持不变,除了   用于执行构造函数和   声明的对象的析构函数   异常声明。

     

注意:强调我的

答案 1 :(得分:4)

这是编译器支持的返回值优化(RVO)功能的示例。

按值返回时,可能无法调用复制构造函数

在GCC上使用-fno-elide-constructors选项关闭该功能。

答案 2 :(得分:2)

我相信它被称为return value optimization

我假设当f()返回C对象时,对象被分配在调用方法的堆栈空间中,因此不需要复制来初始化C a。这是您的default C called

C b = a

这会导致复制构造函数为CC called

顺便说一句,wiki上的示例与您的代码非常相似。