为什么在以下程序中不调用复制构造函数?

时间:2012-10-18 08:26:46

标签: c++

  

可能重复:
  Why copy constructor is not called in this case?

考虑以下代码段:

#include <iostream>

using namespace std;

class Test
{
        char name[16];
        public:
        Test ()
        {
                cout <<"Inside Constructor"<<endl;
        }

        Test (const Test & t)
        {
                cout <<"Inside Copy Constructor "<<endl;
        }

};

Test f()
{
        return Test();
}

int main ( int argc, char ** argv)
{
        Test t;
        Test t1 = f();

}

测试t1 = f() - &gt;它调用f(),并返回Test对象,然后根据我的理解,应该调用复制构造函数。但我得到以下输出:

Inside Constructor
Inside Constructor

我的理解有什么问题?。

4 个答案:

答案 0 :(得分:2)

这里会出现两个副本。

第一种是返回值优化(而不是将表达式Test()的结果复制到临时对象,即f的返回值,表达式Test()是通过直接构造临时对象来评估,该临时对象是f)的返回值。

第二个是从初始化表达式t1t1本身的副本的省略(因此不是将f的返回值临时复制到{{1} }},t1的返回值临时直接构造到f)。

两个部门链接在一起 - 因此t1的内存在构造t1的返回值时用作目标,而f的返回值的内存是在构建f时用作目的地。因此实际上Test()由no-args构造函数直接初始化,并且不需要副本。

复制构造函数elision在C ++ 03的12.8 / 15和C ++ 11的12.8 / 31中的标准中定义(也允许省略移动)。它需要特定的权限,因为它改变了程序的可观察行为(在您的情况下,它省略了复制构造函数的副作用,输出)。因此它只能在标准中定义的条件下执行

这两个元素都是C ++ 03中允许的第二个允许省略的例子(C ++ 11中的第三个),当源是临时的时。

第一个允许的省略通常称为“命名返回值优化”,它允许在源不是临时源时省略特定类型的副本。

答案 1 :(得分:1)

因为return value optimisation删除了所需的额外副本。

答案 2 :(得分:1)

它被称为return value optimization

答案 3 :(得分:0)

好吧,我认为你永远不会调用复制构造函数。您调用默认构造函数,获取临时副本,然后调用赋值运算符。

EDIT。好的,我想念Test t1 = f();。 RVO确实最有可能在f()踢。 所以它基本上等于Test t1 = Test();

我认为这是允许应用的一些优化,即使它可能导致程序的更改行为。如果你使用优化标志进行修改,你可能会让它执行一个复制构造函数(旧对象上的+析构函数)。