按值返回是否调用复制构造函数或复制赋值运算符?

时间:2015-11-19 04:54:57

标签: c++ constructor return-value copy-constructor compiler-optimization

假设编译器中没有返回值optimizaiton 在c ++中,当对象在函数中返回vaule时,真正的步骤在下面,我是否正确?总的来说,第三次调用构造函数。

本地(普通建筑师) - > temp (复制构造函数)---> 外部(复制构造函数或复制assignemt运算符)

  1. 创建了一个本地对象,这里调用普通构造函数;
  2. 使用本地对象创建了一个临时对象,这里它调用了copy constructor;
  3. 将临时对象分配给(a)之外的真实对象,这里它调用复制构造函数(case1)或复制赋值运算符(case2)
  4. class Name{...};
    
    Name func(){
        // ...
        Name local;
        return local;
    }
    

    情形1:

    Name outside  = func(); // call copy constructor?
    

    情况2:

    Name outside;
    outside = func(); // call copy assignment operator?
    

    如果我在第一部分是正确的,如果启用了返回值优化会怎么样?

2 个答案:

答案 0 :(得分:1)

这个问题让我思考,所以从这个意义上来说这是一个很好的问题。我在Visual Studio C ++ Express 2010中运行下面的测试代码" Debug"模式。

#include <iostream>

using namespace std;

class Foo
{
public:
    Foo(int arg) { val = arg; cout<<"Constructor (normal): "<<val<<endl; }
    Foo(const Foo& ref) { val = ref.val; cout<<"Copy constructor: "<<val<<endl; }
    const Foo& operator=(const Foo& rval)
    {
        cout<<"Assignment operator from object "<<rval.val<<" to object "<<val<<endl;
        val = rval.val; 
        return *this;
    }


    int val;
};

Foo process() {Foo t(2); return t; }

int main()
{
    Foo a(1);
    a = process();

    system("pause");
    return 0;
}

结果:

    Constructor (normal): 1
    Constructor (normal): 2
    Copy constructor: 2
    Assignment operator from object 2 to object 1
    Press any key to continue . . .

案例2似乎是正确的。在外部&#39; Foo&#39;构建了'Foo&#39; object是在函数内部构造的。然后使用复制构造函数创建另一个对象,最后调用赋值运算符将结果复制到对象a。

返回值优化将取决于编译器和设置。例如,当我在发布模式下构建和运行时,没有调用复制构造函数,表明临时对象仅用于调试模式。 (我不是这个主题的专家。)

答案 1 :(得分:1)

C ++中的复制省略/返回值优化允许它跳过调用复制构造函数。

案例1,您在返回中使用了复制构造并构建了实例&#34;在&#34;之外。这些中的任何一个或两个都可以省略。 即使C ++具有可测量的副作用,也允许C ++忽略这些函数调用 - 不适用as-if规则。

案例2您正在使用赋值运算符将值输入变量&#34;在&#34;之外,非依赖于复制省略的异常在此处不适用。因此,您将获得一个赋值操作符调用,除非编译器可以安全地忽略它,因为它没有副作用。在后一种情况下,编译器可以自由选择,但根据定义,你很难说出发生了什么。