0%

为什么函数返回对象时没有调用复制构造函数?

1. 复制构造函数被调用的三种情况

  1. 使用已有的对象创建新的对象。

    1
    2
    A a1(a);
    A a2 = a;
  2. 函数的参数类型是对象。

    1
    void func(A a);
  3. 函数返回值的类型是对象。

    1
    A func();

2. 示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>

using namespace std;

class A {
public:
A() { cout << "constructor" << endl; }
~A() { cout << "destructor" << endl; }
A(const A& a) { cout << "copy constructor" << endl; }
};

A func() {
A a;
cout << "func()" << endl;
return a;
}

int main()
{
A a = func();

cout << "return" << endl;
return 0;
}

运行结果为:

1
2
3
4
constructor        // A a = func()调用func中A a
func()
return // main结束
destructor // 析构a

而相较预期的结果少了func()返回值的临时对象的复制构造函数,和用函数返回值生成A a对象的复制构造函数。

3. 原因

产生这个问题的原因是编译器进行了返回值优化RVO,减少了不必要对象的构造,提高效率。

以下内容摘自维基百科

返回值优化(Return value optimization,缩写为RVO)是C++的一项编译优化技术。即删除保持函数返回值的临时对象。这可能会省略两次复制构造函数,即使复制构造函数有副作用。