编译器绕过拷贝构造函数和返回值优化

发布时间 2023-05-31 16:11:48作者: 小凉拖

写在前面:

在拷贝初始化(也就是用等号初始化,注意使用拷贝构造函数创建一个新的对象不属于拷贝初始化)过程中,编译器可以(但不是必须)跳过拷贝构造函数或者移动构造函数,直接创建对象。

1 string null_book="999";
2 //可以改写为
3 string null_book("999");

这里面”999“隐式的转换为string对象,例如:string temp("999");,然后执行拷贝构造函数:string null_book=temp;

但是者里面的拷贝构造被忽略掉了。

这里面举个黑马程序员的例子:

 1 class Person
 2 {
 3 public:
 4     Person()
 5     {
 6         cout << "Person的默认构造函数调用" 
 7             << "地址为:"
 8             << this
 9             << endl;
10     }
11     Person(int age):age_(age)
12     {
13         cout << "Person有参构造函数调用" 
14             << "地址为:"
15             << this
16             << endl;
17     }
18     Person(const Person& p)
19     {
20         cout << "Person的拷贝构造函数调用" 
21             <<"地址为:"
22             <<this
23             << endl;
24         
25     }
26     ~Person()
27     {
28         cout << "Person的析构函数调用" 
29             << "地址为:"
30             << this
31             << endl;
32     }
33     int age_;
34 };
35 
36 Person dowork()
37 {
38     Person p3;
39     return p3;
40 }
41 void test03()
42 {
43     Person p4 = dowork();
44 }
45 
46 int main()
47 {
48     test03();
49     system("pause");
50     return 0;
51 }

运行结果为:

 在没有运行之前个人猜测运行结果会是这样的:

首先p3在创建的时候会调用默认构造。

然后在运行return语句的时候系统会创建一个临时的对象temp会接收到p3此时调用拷贝构造

然后将p3析构掉

然后,在test03函数中Person p4 = dowork();会调用拷贝构造函数,将temp拷贝给p4

然后当test03执行结束后会析构掉p4。

(这里面我有个问题就是temp什么时候被析构掉呢,黑马程序员的代码中也没有解释p'何时被析构掉,我想这个应该是返回值的知识,也就是返回的时候创建这个临时的temp的生命周期到底是多久,是在调用点将值传递给接收的变量吗)。

然而运行结果却只有默认构造和它的析构也就是对象p3。

这里面在返回的时候编译器采用了返回值优化,也就是没有创建那个临时的对象temp,是直接将p3复制到了test03中的p4的内存空间中去了因此这一次的拷贝构造就没了,然后执行Person p4 = dowork();时采用的是拷贝初始化,这个地方也不会调用拷贝构造,所以这一步也没有发生拷贝构造。

以上是个人的理解

再来看一个例子:

也就是对象在值传递的时候会发生拷贝构造,注意这里是实参赋值给形参发生的拷贝构造,不是拷贝初始化。

 1 class Person
 2 {
 3 public:
 4     Person()
 5     {
 6         cout << "Person的默认构造函数调用" 
 7             << "地址为:"
 8             << this
 9             << endl;
10     }
11     Person(int age):age_(age)
12     {
13         cout << "Person有参构造函数调用" 
14             << "地址为:"
15             << this
16             << endl;
17     }
18     Person(const Person& p)
19     {
20         cout << "Person的拷贝构造函数调用" 
21             <<"地址为:"
22             <<this
23             << endl;
24         
25     }
26     ~Person()
27     {
28         cout << "Person的析构函数调用" 
29             << "地址为:"
30             << this
31             << endl;
32     }
33     int age_;
34 };
35 void test02(Person p2)
36 {
37 
38 }
39 
40 int main()
41 {
42     Person p1;
43     test02(p1);
44     system("pause");
45     return 0;
46 }