复制构造函数重载

本文深入探讨C++中复制构造函数的调用机制,特别是如何在函数返回值和临时对象处理中选择正确的复制构造函数。通过具体代码示例,解释了普通引用与const引用在函数参数传递中的不同作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先看代码:
以下代码编译时要加:-fno-elide-constructors 来关闭编译器优化,否则可能看不到复制构造函数的调用。

#include <iostream>

using std::cout;
using std::endl;

class A {
  public:
	A() = default;

	A(A& a)
	{
		cout << "copy constructor1 is called." << endl;
	}

	A(const A& a)
	{
		cout << "copy constructor2 is called." << endl;
	}
};

A createA()
{
	return A();
}

A createA2()
{
	A a;
	return a;
}

int main()
{
	A a;

	A b = a;
	cout << "==============" << endl;
	createA();
	cout << "==============" << endl;
	
	cout << "==============" << endl;
	createA2();
	cout << "==============" << endl;
	A d = createA2();

	return 0;
}

输出结果:

copy constructor1 is called.
===============
copy constructor2 is called.
===============
copy constructor2 is called.
copy constructor2 is called.
===============
copy constructor1 is called.
===============
copy constructor1 is called.
copy constructor2 is called.

下面主要解释一下A c = createA(); 为什么执行第二个复制构造函数。

我们知道,C++运行时会产生临时对象,而这个临时对象我们是不能对其进行操作的,比如修改这个临时变量的值是做不到的,因为这个临时变量由编译器复杂生成,对我们不可见。
而C++认为如果一个函数的参数是一个普通引用(非const),那么这个变量(实参)应该是能够被修改的,比如我们传入一个普通变量是没有问题的,这个普通变量是可以修改的。
但是临时变量对我们是不可修改的,那么临时变量就不能作为普通引用(非const)传入函数(违反了上面所说的编译器的要求:可以被修改)
所以当A c = createA(); 时,createA()的返回值是一个临时变量,那么它不能作为普通引用(非const), 也就是不能调用第一个复制构造函数,必须调用第二个复制构造函数。(如果注释掉第二个,编译不通过)

那么在createA()和createA2()时为什么调用不同的复制构造函数呢?
函数返回时调用复制构造函数其实是为那个临时变量进行构造(生成临时变量),而参数就是return 后面的对象(return A(), return a;),
对于return A()来说 A()是也是一个临时变量,分析同上,也要调用第二个复制构造函数。
对于return a来说,这个a,它不是一个临时变量(我们自己定义的),所以可调用第一个复制构造函数。

A c = createA()或A d = createA2()过程大体如下:
在这里插入图片描述
S1就是return后面的对象(A(), a), 对于A()是个临时的,a不是临时对象(调用第一次copy constructor时的参数,决定了调用哪个copy constructor)
S2就是函数的返回值空间(对象),一定是临时的。(调用第二次copy constructor时的参数,决定了调用第二个copy constructor)
S3是变量c/d。

编译器对返回值的一般处理方式:
主调函数创建一段内存空间用于存放返回的对象(也就是上图中的临时空间S2),主调函数调用被调函数时,将该内存空间作为参数传入被调函数中(编译器自动完成,无需程序员自己显性写出)。因此,返回值所生成的对象的内存分配和构造是分步执行的,在主调函数中分配内存,在被调函数中进行构造。


以上为个人理解,如有错误,还望指正。

参考:
https://blog.youkuaiyun.com/qq_41791653/article/details/82354114
https://www.cnblogs.com/area-h-p/p/11498481.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值