P18-c++复制构造函数深度剖析介绍,详细的例子演示!

1.特殊成员函数

C++里面一些类的成员函数是自动定义的,具体地说,C++自动提供了下面这些成员函数:

  • 默认构造函数,如果没有定义构造函数;
  • 默认析构函数,如果没有定义;
  • 复制构造函数,如果没有定义
  • 赋值运算符,如果没有定义
  • 地址运算符,如果没有定义

更准确地说,编译器将生成上述最后三个函数的定义, 如果你涉及到了上面的操作,而没有显式提供这些函数的话。

例如, 如果您将一个对象赋给另一个对象,编译器将提供赋值运算符的定义。下面用代码的形式来描述:
Demo 是本文当中演示使用到的类,有下面语句

Demo d;
Demo d1;
d = d1; // 会被编译器翻译成 d.operator=(d1);

因为 = 赋值运算符只能当作成员函数来进行重载
运算符重载只能是成员函数
所以class_name_c1 = class_name_c2; 这样的语句,class_name_c1会是那个调用的对象,而 class_name_c2 会是传递的形参,即 class_name_c1.operator=(class_name_c2);

2.复制构造函数

复制构造函数用于将一个对象复制到新创建的对象中
也就是说,它用于初始化过程中(包括按值传递参数),而不是常规的赋值过程中。类的复制构造函数原型通常如下:

Class_name(const Class_name &);

它接受一个指向类对象的常量引用作为参数。例如, Demo类的复制构造函数的原型如下

Demo(const Demo &);

对于复制构造函数,需要知道两点:何时调用和有何功能。

3.何时调用复制构造函数

1.新建一个对象并将其初始化为同类现有对象时,复制构造函数都将被调用

这在很多情况下都可能发生,最常见的情况是将新对象显式地初始化为现有的对象。
例如,假设m1是一个 Demo对象,则下面4种声明都将调用复制构造函数:

Demo d1(m1); // # 1 calls Demo(const Demo &)
Demo d1 = m1; //#2 calls Demo(const Demo &)
Demo d1 = Demo(m1);// #3 calls Demo(const Demo &)
Demo *pDemo =new Demo(m1);//#4  calls Demo(const Demo &)

其中中间的2种声明可能会使用复制构造函数直接创建metoo和also,也可能使用复制构造函数生成一个临时对象,然后将临时对象的内容赋给 metoo和also,这取决于具体的实现。
最后一种声明使用 motto初始化一个匿名对象,并将新对象的地址赋给 pDemo指针。

上面的4条语句,可以参考本文的 copy_constructor.cpp 实际的例子演示!

copy_constructor.cpp演示初始化对象调用复制构造函数的情景?

2. 每当程序生成了对象副本时,编译器都将使用复制构造函数。

具体地说,当函数按值传递对象函数返回对象时,都将使用复制构造函数。
即下面两种情况
第一种情况

Demo d1(1, "d1");
void func(Demo d_var)
{
    
    
	cout << "func(Demo d_var)" << endl;
}

func(d1); //这会导致复制构造函数被调用。用来创建 d_var

第二种情况
func执行完毕 d1就被释放了,return 的时候肯定会调用复制构造函数,将其保存下来。

Demo func()
{
    
    
	Demo d1(1, "d1");
	cout << "func()" << endl;
	return d1;
}

后面也有详细的代码演示。
记住,按值传递意味着创建原始变量的个副本,编译器生成临时对象时,也将使用复制构造函数。

4. copy_constructor.cpp演示初始化对象调用复制构造函数的情景?

1.第一种 Demo d1(m1);

我们先来看Demo类的定义
他有两个成员变量,一个是iAge代表年龄,一个是var_name 他代表的是类对象实例的名字, 例如在使用构造函数的时候就把这个变量名字传递进去 Demo demo(1, "demo"); 这样做的目的是为了,打印的时候区分每个地址对应的是哪一个对象。

class Demo {
    
    
private:
	int iAge;
	string var_name;
public:
	Demo() {
    
    
		iAge = 0;
		var_name = "temp";
		cout << "Demo(), this(" << this->var_name << "):" << this << ", this->iAge:" << this->iAge << endl;
	}
	Demo(int i, string  name = "meng-yue") {
    
    
		this->iAge = i;
		this->var_name = name;
		cout << "Demo(int i),this(" << this->var_name << "):" << this << ", i:" << i << ", this->iAge:" << this->iAge << endl;
	}
	Demo(const Demo & d_copy) {
    
    
		cout << "Demo(const Demo &d),this(" << this->var_name << "):" << this << ", &d_copy(" << d_copy.var_name <<  "):" << &d_copy << endl;
	}
	~Demo() {
    
    
		cout << "~Demo,this(" << this->var_name << "):" << this << endl;
	}
	void Show() {
    
    

	}
};

main函数

	cout << "---------------开始--->公众号:梦悦foundation---------------" << endl;
	Demo m1(1, "m1");
	Demo d1(m1);
	cout << "&d1:" << &d1 << endl;
	cout << "---------------结束--->公众号:梦悦foundation---------------" << endl;

copy_constructor.cpp

  /*
	 author:梦悦foundation
	 公众号:梦悦foundation
	 可以在公众号获得源码和详细的图文笔记
 */
 
#include <iostream>
#include <typeinfo>
#include <string>
 
using namespace std;
class Demo {
    
    
private:
	int iAge;
	string var_name;
public:
	Demo() {
    
    
		iAge = 0;
		var_name = "temp";
		cout << "Demo(), this(" << this->var_name << "):" << this << ", this->iAge:" << this->iAge << endl;
	}
	Demo(int i, string  name = "meng-yue") {
    
    
		this->iAge = i;
		this->var_name = name;
		cout << "Demo(int i),this(" << this->var_name << "):" << this << ", i:" << i << ", this->iAge:" << this->iAge << endl;
	}
	Demo(const Demo & d_copy) {
    
    
		cout << "Demo(const Demo &d),this(" << this->var_name << "):" << this << ", &d_copy(" << d_copy.var_name <<  "):" << &d_copy << endl;
	}
	~Demo() {
    
    
		cout << "~Demo,this(" << this->var_name << "):" << this << endl;
	}
	void Show() {
    
    

	}
};
int main()
{
    
    
	cout << "---------------开始--->公众号:梦悦foundation---------------" << endl;
	Demo m1(1, "m1");
	Demo d1(m1);
	cout << "&d1:" << &d1 << endl;
	cout << "---------------结束--->公众号:梦悦foundation---------------" << endl;
	return 0;
}

编译运行的结果:
首先 执行Demo m1(1, "m1"); 然后能够看出来 m1 的地址是 0xbfb06380
然后执行 Demo d1(m1); 这会导致复制构造函数的调用,去构造这一个新的类实例 d1;,然后能看到这个d1 的地址是 0xbfb06378, 同时它的name 是没有值,
Demo(const Demo &d),this():0xbfb06378, &d_copy(m1):0xbfb06380

book@book-desktop:~/meng-yue/c++/class_dynamic_memory/02$ ./copy_constructor
---------------开始--->公众号:梦悦foundation---------------
Demo(int i),this(m1):0xbfb06380, i:1, this->iAge:1
Demo(const Demo &d),this():0xbfb06378, &d_copy(m1):0xbfb06380
&d1:0xbfb06378
---------------结束--->公众号:梦悦foundation---------------
~Demo,this():0xbfb06378
~Demo,this(m1):0xbfb06380
book@book-desktop:~/meng-yue/c++/class_dynamic_memory/02$

上面 d1 成员变量没有值的原因是因为我们的复制构造函数什么都没有干的原因。假如说我们不提供自己定义的复制构造函数,c++为类默认生成的复制构造函会采取逐个成员赋值的操作!即

d1.iAge = m1.iAge;
d1.var_name = m1.var_name;

我们可以把自己写的那个默认构造函数注释掉,并且新增一个Show(),打印成员变量,看看运行的结果:
在这里插入图片描述

默认的赋值构造函数有什么问题?

default_copy_constructor.cpp

  /*
	 author:梦悦foundation
	 公众号:梦悦foundation
	 可以在公众号获得源码和详细的图文笔记
 */
 
#include <iostream>
#include <typeinfo>
#include <string>
 
using namespace std;
class Demo {
    
    
private:
	int iAge;
	string var_name;
public:
	Demo() {
    
    
		iAge = 0;
		var_name = "temp";
		cout << "Demo(), this(" << this->var_name << "):" << this << ", this->iAge:" << this->iAge << endl;
	}
	Demo(int i, string  name = "meng-yue") {
    
    
		this->iAge = i;
		this->var_name = name;
		cout << "Demo(int i),this(" << this->var_name << "):" << this << ", i:" << i << ", this->iAge:" << this->iAge << endl;
	}
#if 0	
	Demo(const Demo & d_copy) {
    
    
		cout << "Demo(const Demo &d),this(" << this->var_name << "):" << this << ", &d_copy(" << d_copy.var_name <<  "):" << &d_copy << endl;
	}
#endif	
	~Demo() {
    
    
		cout << "~Demo,this(" << this->var_name << "):" << this << endl;
	}
	void Show() {
    
    
		cout << "Show(),this(" << this->var_name << "):" << this << ", this->iAge:" << this->iAge << endl;;
	}
};
int main()
{
    
    
	cout << "---------------开始--->公众号:梦悦foundation---------------" << endl;
	Demo m1(1, "m1");
	Demo d1(m1);
	cout << "&d1:" << &d1 << endl;
	d1.Show();
	cout << "---------------结束--->公众号:梦悦foundation---------------" << endl;
	return 0;
}

编译运行的结果:
可以看出来 ,之前的分析默认的复制构造函数确实是按照逐成员复制的。
在这里插入图片描述
注意: 所以默认复制构造函数有一个隐患就是 因为是按值赋值,所以var_name 实际上指向的是同一块内存区域。所以需要定义自己的复制构造函数,防止析构的时候重复析构同一块内存区域!
在这里插入图片描述

2. 第二种 Demo d1 = m1;

copy_constructor1.cpp

int main()
{
    
    
	cout << "---------------开始--->公众号:梦悦foundation---------------" << endl;
	Demo m1(1, "m1");
	Demo d1 = m1;
	cout << "&d1:" << &d1 << endl;
	cout << "---------------结束--->公众号:梦悦foundation---------------" << endl;
	return 0;
}

编译运行的结果:
确实调用了复制构造函数。

book@book-desktop:~/meng-yue/c++/class_dynamic_memory/02$ ./copy_constructor1
---------------开始--->公众号:梦悦foundation---------------
Demo(int i),this(m1):0xbfbafbd0, i:1, this->iAge:1
Demo(const Demo &d),this():0xbfbafbc8, &d_copy(m1):0xbfbafbd0
&d1:0xbfbafbc8
---------------结束--->公众号:梦悦foundation---------------
~Demo,this():0xbfbafbc8
~Demo,this(m1):0xbfbafbd0
book@book-desktop:~/meng-yue/c++/class_dynamic_memory/02$

3. 第3种 Demo d1 = Demo(m1);

copy_constructor2.cpp

	cout << "---------------开始--->公众号:梦悦foundation---------------" << endl;
	Demo m1(1, "m1");
	Demo d1 = Demo(m1);
	cout << "&d1:" << &d1 << endl;
	cout << "---------------结束--->公众号:梦悦foundation---------------" << endl;
	return 0;
}

编译运行的结果:
确实调用了复制构造函数。

book@book-desktop:~/meng-yue/c++/class_dynamic_memory/02$ ./copy_constructor2
---------------开始--->公众号:梦悦foundation---------------
Demo(int i),this(m1):0xbfdfd890, i:1, this->iAge:1
Demo(const Demo &d),this():0xbfdfd888, &d_copy(m1):0xbfdfd890
&d1:0xbfdfd888
---------------结束--->公众号:梦悦foundation---------------
~Demo,this():0xbfdfd888
~Demo,this(m1):0xbfdfd890
book@book-desktop:~/meng-yue/c++/class_dynamic_memory/02$

4. 第4种 Demo *pDemo = new Demo(m1);

copy_constructor3.cpp

	cout << "---------------开始--->公众号:梦悦foundation---------------" << endl;
	Demo m1(1, "m1");
	Demo *pDemo = new Demo(m1);
	cout << "pDemo:" << pDemo << endl;
	cout << "---------------结束--->公众号:梦悦foundation---------------" << endl;
	return 0;

编译运行的结果:
确实调用了复制构造函数。

book@book-desktop:~/meng-yue/c++/class_dynamic_memory/02$ ./copy_constructor3
---------------开始--->公众号:梦悦foundation---------------
Demo(int i),this(m1):0xbf8bd8cc, i:1, this->iAge:1
Demo(const Demo &d),this():0x8a24020, &d_copy(m1):0xbf8bd8cc
pDemo:0x8a24020
---------------结束--->公众号:梦悦foundation---------------
~Demo,this(m1):0xbf8bd8cc
book@book-desktop:~/meng-yue/c++/class_dynamic_memory/02$

5. 第5种,func(Demo d_var)

copy_constructor4.cpp

void func(Demo d_var)
{
    
    
	cout << "func(Demo d_var)" << endl;
}

int main()
{
    
    
	cout << "---------------开始--->公众号:梦悦foundation---------------" << endl;
	Demo d1(1, "d1");
	func(d1);
	cout << "---------------结束--->公众号:梦悦foundation---------------" << endl;
	return 0;
}

编译运行的结果:
确实调用了复制构造函数。

book@book-desktop:~/meng-yue/c++/class_dynamic_memory/02$ ./copy_constructor4
---------------开始--->公众号:梦悦foundation---------------
Demo(int i),this(d1):0xbfbaa140, i:1, this->iAge:1
Demo(const Demo &d),this():0xbfbaa138, &d_copy(d1):0xbfbaa140
func(Demo d_var)
~Demo,this():0xbfbaa138
---------------结束--->公众号:梦悦foundation---------------
~Demo,this(d1):0xbfbaa140
book@book-desktop:~/meng-yue/c++/class_dynamic_memory/02$

6. 第6种,Demo func(),引发了很多思考

copy_constructor5.cpp

Demo func()
{
    
    
	Demo d1(1, "d1");
	cout << "func()" << endl;
	return d1;
}


int main()
{
    
    
	cout << "---------------开始--->公众号:梦悦foundation---------------" << endl;
	func();
	cout << "---------------结束--->公众号:梦悦foundation---------------" << endl;
	return 0;
}

编译运行的结果:
发现并没有调用复制构造函数,这是为什么呢?

book@book-desktop:~/meng-yue/c++/class_dynamic_memory/02$ ./copy_constructor5
---------------开始--->公众号:梦悦foundation---------------
Demo(int i),this(d1):0xbfc7e4a8, i:1, this->iAge:1
func(Demo d_var)
~Demo,this(d1):0xbfc7e4a8
---------------结束--->公众号:梦悦foundation---------------
book@book-desktop:~/meng-yue/c++/class_dynamic_memory/02$

刚开始我以为是没有人使用它的返回值,这种情况如果我是写编译器的人肯定是会优化掉的。因为没有人使用返回值,就不用浪费一次复制构造函数执行的开销。
所以我改了一下代码,改成下面这样。
copy_constructor6.cpp

	Demo d2 = func();
	d2.Show(); //这是把成员变量都打印出来,看看d2的成员变量有没有被改变

编译运行结果:
可以看出来 d2这个对象确实和d1一样,但是却没有调用复制构造函数来完成这个工作,那是谁在起作用?

book@book-desktop:~/meng-yue/c++/class_dynamic_memory/02$ g++ -o copy_constructor5 copy_constructor5.cpp
book@book-desktop:~/meng-yue/c++/class_dynamic_memory/02$ ./copy_constructor5
---------------开始--->公众号:梦悦foundation---------------
Demo(int i),this(d1):0xbfe02298, i:1, this->iAge:1
func()
Show(),this(d1):0xbfe02298, this->iAge:1
---------------结束--->公众号:梦悦foundation---------------
~Demo,this(d1):0xbfe02298
book@book-desktop:~/meng-yue/c++/class_dynamic_memory/02$

先来看看原因,c++提供了一个返回优化,RVO(return value optimization),被g++进行优化了。

  -fno-elide-constructors
      The C++ standard allows an implementation to omit creating a temporary that is only used to initialize
     another object of the same type.  Specifying this option disables that optimization, and forces g++ to
      call the copy constructor in all cases.

我们可以在编译的时候,指定选项 -fno-elide-constructors 来关闭 这个返回优化
copy_constructor7.cpp
g++ -fno-elide-constructors -o copy_constructor7 copy_constructor7.cpp

int main()
{
    
    
	cout << "---------------开始--->公众号:梦悦foundation---------------" << endl;
	func();
	cout << "---------------结束--->公众号:梦悦foundation---------------" << endl;
	return 0;
}

编译运行的结果:
可以看出来,关闭掉返回优化,确实复制构造函数就调用了。

book@book-desktop:~/meng-yue/c++/class_dynamic_memory/02$ ./copy_constructor7
---------------开始--->公众号:梦悦foundation---------------
Demo(int i),this(d1):0xbff2a42c, i:1, this->iAge:1
func()
Demo(const Demo &d),this():0xbff2a468, &d_copy(d1):0xbff2a42c
~Demo,this(d1):0xbff2a42c
~Demo,this():0xbff2a468
---------------结束--->公众号:梦悦foundation---------------
book@book-desktop:~/meng-yue/c++/class_dynamic_memory/02$

但是,这不能够解释 Demo d2 = func(); 这条语句为什么会生效,因为它省略了复制构造函数这个临时对象的生成,那就不会调用复制构造函数,那是谁给d2赋值的呢??
关于重载赋值运算符的知识
P18-c++复制构造函数深度剖析介绍,详细的例子演示!
这是个疑问,我也不知道,记录下来
我本来以为是c++提供的默认的operator=()函数做的,但是我显示的提供可这个函数,发现也没有调用!
这里也有两种情况,一种是初始化的时候,返回类对象,像下面这样

	cout << "---------------开始--->公众号:梦悦foundation---------------" << endl;
	Demo d2 = func();
	d2.Show();
	cout << "---------------结束--->公众号:梦悦foundation---------------" << endl;
	return 0;

另外一种是这样,给已存在的对象赋值

Demo d2(2, "d2");
d2 = func();

这里也分别看看这两种情况的运行结果
copy_constructor8.cpp 对应的是上面的第一种情况!
新增加了 一个 operator=() 成员函数。

  /*
	 author:梦悦foundation
	 公众号:梦悦foundation
	 可以在公众号获得源码和详细的图文笔记
 */
 
#include <iostream>
#include <typeinfo>
#include <string>
 
using namespace std;
class Demo {
    
    
private:
	int iAge;
	string var_name;
public:
	Demo() {
    
    
		iAge = 0;
		var_name = "temp";
		cout << "Demo(), this(" << this->var_name << "):" << this << ", this->iAge:" << this->iAge << endl;
	}
	Demo(int i, string  name = "meng-yue") {
    
    
		this->iAge = i;
		this->var_name = name;
		cout << "Demo(int i),this(" << this->var_name << "):" << this << ", i:" << i << ", this->iAge:" << this->iAge << endl;
	}
	Demo(const Demo & d_copy) {
    
    
		cout << "Demo(const Demo &d),this(" << this->var_name << "):" << this << ", &d_copy(" << d_copy.var_name <<  "):" << &d_copy << endl;
	}
	
	Demo & operator=(const Demo & d_var) {
    
    
		cout << "operator=(const Demo&d_var),this(" << this->var_name << "):" << this << ", &d_var(" << d_var.var_name <<  "):" << &d_var;
		cout << ", this->iAge:" << this->iAge << ", d_var.iAge:" << d_var.iAge << endl;
	}
	~Demo() {
    
    
		cout << "~Demo,this(" << this->var_name << "):" << this << endl;
	}
	void Show() {
    
    
		cout << "Show(),this(" << this->var_name << "):" << this << ", this->iAge:" << this->iAge << endl;;
	}
};

Demo func()
{
    
    
	Demo d1(1, "d1");
	cout << "func()" << endl;
	return d1;
}


int main()
{
    
    
	cout << "---------------开始--->公众号:梦悦foundation---------------" << endl;
	Demo d2 = func();
	d2.Show();
	cout << "---------------结束--->公众号:梦悦foundation---------------" << endl;
	return 0;
}

编译运行结果:

book@book-desktop:~/meng-yue/c++/class_dynamic_memory/02$ g++ -o copy_constructor8 copy_constructor8.cpp
book@book-desktop:~/meng-yue/c++/class_dynamic_memory/02$ ./copy_constructor8
---------------开始--->公众号:梦悦foundation---------------
Demo(int i),this(d1):0xbfaeb648, i:1, this->iAge:1
func()
Show(),this(d1):0xbfaeb648, this->iAge:1
---------------结束--->公众号:梦悦foundation---------------
~Demo,this(d1):0xbfaeb648
book@book-desktop:~/meng-yue/c++/class_dynamic_memory/02$

结果发现,既没有调用复制构造函数,也没有调用 operator=(),但是很神奇的是,d2 的值 跟d1 一模一样了。
这个地方要留下一个疑问,是谁在默默付出??

我们尝试将返回优化关闭掉去

g++ -fno-elide-constructors -o copy_constructor8 copy_constructor8.cpp

编译运行的结果:
这个结果很有意思,对比一下之前没有关闭返回优化的,d2 的成员变量是都被赋值的(从d2.Show() 的输出能够看出来),
Show(),this():0xbf917398, this->iAge:-1080986680 没有被赋值,都是空的。
我们从头开始分析一下代码:
首先调用 func(), 这个函数里面创建了一个 Demo对象 Demo d1(1, "d1");,所以打印了下面的构造函数。

Demo(int i),this(d1):0xbf91735c, i:1, this->iAge:1

接着就 return d1;, 我们关闭掉返回优化,可想而知,这需要一个临时变量来接收d1 这个类对象,因为d1 在执行完 func() 作用域就结束了。
所以 return d1 就相当于下面这样一条语句

Demo temp = d1;

所以这个时候会调用赋值构造函数创建 temp这个临时对象,所以会有下面的打印

Demo(const Demo &d),this():0xbf917390, &d_copy(d1):0xbf91735c

结合复制构造函数的原型 Demo(const Demo & d_copy),d_copy 就是 要复制的 d1。
这个临时对象temp的地址是0xbf917390,而且d_copy 的名字也确实是d1, 然后地址 是0xbf91735c ,这个可以与前面构造d1的时候的地址进一步确认Demo(int i),this(d1):0xbf91735c, i:1, this->iAge:1 地址是一模一样的。

紧接着 d1就被析构了。所以代码就相当于变成了

Demo d2 = temp;

同理这会导致复制构造函数的调用,temp是复制构造函数的形参,从打印也能看出来, d_copy 的地址是 0xbf917390,也确实是这个临时变量temp的地址。

Demo(const Demo &d),this():0xbf917398, &d_copy():0xbf917390

d2 的地址是 0xbf917398。从最后的 d2.Show()打印能够对的上。
不过因为关闭掉了返回优化,发现使用了复制构造函数,但是复制构造函数里面并没有做任何拷贝工作。所以 d2的成员变量的值都是空的。

Show(),this():0xbf917398, this->iAge:-1080986680
book@book-desktop:~/meng-yue/c++/class_dynamic_memory/02$ ./copy_constructor8
---------------开始--->公众号:梦悦foundation---------------
Demo(int i),this(d1):0xbf91735c, i:1, this->iAge:1
func()
Demo(const Demo &d),this():0xbf917390, &d_copy(d1):0xbf91735c
~Demo,this(d1):0xbf91735c
Demo(const Demo &d),this():0xbf917398, &d_copy():0xbf917390
~Demo,this():0xbf917390
Show(),this():0xbf917398, this->iAge:-1080986680
---------------结束--->公众号:梦悦foundation---------------
~Demo,this():0xbf917398
book@book-desktop:~/meng-yue/c++/class_dynamic_memory/02$

copy_constructor9.cpp 演示的是上面的另一种情况,给已存在的对象赋值
其他部分和copy_constructor9.cpp是一模一样的,只是更改了main()部分

int main()
{
    
    
	cout << "---------------开始--->公众号:梦悦foundation---------------" << endl;
	Demo d2(2, "d2");
	d2 = func();
	d2.Show();
	cout << "---------------结束--->公众号:梦悦foundation---------------" << endl;
	return 0;
}

编译运行的结果:
发现赋值运算符确实调用了,因为这是给已有的对象赋值。
而且这个地方你发现,operator=()是在d1还存活的时候运行的,你从打印能看出来

func()
operator=(const Demo&d_var),this(d2):0xbff7a750, &d_var(d1):0xbff7a748, this->iAge:2, d_var.iAge:1
~Demo,this(d1):0xbff7a748

而且,这个打印相当于 d2.operator=(d1),调用完了 赋值函数,才析构掉d1的。

book@book-desktop:~/meng-yue/c++/class_dynamic_memory/02$ g++ -o copy_constructor9 copy_constructor9.cpp
book@book-desktop:~/meng-yue/c++/class_dynamic_memory/02$ ./copy_constructor9
---------------开始--->公众号:梦悦foundation---------------
Demo(int i),this(d2):0xbff7a750, i:2, this->iAge:2
Demo(int i),this(d1):0xbff7a748, i:1, this->iAge:1
func()
operator=(const Demo&d_var),this(d2):0xbff7a750, &d_var(d1):0xbff7a748, this->iAge:2, d_var.iAge:1
~Demo,this(d1):0xbff7a748
Show(),this(d2):0xbff7a750, this->iAge:2
---------------结束--->公众号:梦悦foundation---------------
~Demo,this(d2):0xbff7a750
book@book-desktop:~/meng-yue/c++/class_dynamic_memory/02$

那我们同样做个对比,再把返回优化给关闭掉,看看对比结果

book@book-desktop:~/meng-yue/c++/class_dynamic_memory/02$ g++ -fno-elide-constructors -o copy_constructor9 copy_constructor9.cpp
book@book-desktop:~/meng-yue/c++/class_dynamic_memory/02$ ./copy_constructor9
---------------开始--->公众号:梦悦foundation---------------
Demo(int i),this(d2):0xbfeae33c, i:2, this->iAge:2
Demo(int i),this(d1):0xbfeae2fc, i:1, this->iAge:1
func()
Demo(const Demo &d),this():0xbfeae334, &d_copy(d1):0xbfeae2fc
~Demo,this(d1):0xbfeae2fc
operator=(const Demo&d_var),this(d2):0xbfeae33c, &d_var():0xbfeae334, this->iAge:2, d_var.iAge:134524916
~Demo,this():0xbfeae334
Show(),this(d2):0xbfeae33c, this->iAge:2
---------------结束--->公众号:梦悦foundation---------------
~Demo,this(d2):0xbfeae33c
book@book-desktop:~/meng-yue/c++/class_dynamic_memory/02$

你发现,d1是在调用operator=()函数前就被析构了,取而代之的生成了一个临时对象,作为这个赋值函数的参数。
源码资料路径
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/sgy1993/article/details/113793900
今日推荐