您现在的位置是:首页 > 编程 > 

【C++】深入剖析默认成员函数:拷贝构造函数

2025-07-19 16:21:03
【C++】深入剖析默认成员函数:拷贝构造函数 上两篇博客我们深入探讨了一下另外两个默认成员函数:构造函数和析构函数。他们两个都有一个特性:(1)对“内置类型”的成员函数:不进行初始化,也不进行清理(就是没有调用析构函数)。(2)对于“自定义类型”的成员函数:会调用它对应的默认构造函数进行初始化,和对应的析构函数进行清理。而今天我们迎来了第三问默认成员函数---拷贝构造函数!听到“构造”两个字,想

【C++】深入剖析默认成员函数:拷贝构造函数

上两篇博客我们深入探讨了一下另外两个默认成员函数:构造函数和析构函数。

他们两个都有一个特性:

(1)对“内置类型”的成员函数:不进行初始化,也不进行清理(就是没有调用析构函数)。

(2)对于“自定义类型”的成员函数:会调用它对应的默认构造函数进行初始化,和对应的析构函数进行清理。

而今天我们迎来了第三问默认成员函数---拷贝构造函数!

听到“构造”两个字,想必大家马上就意识到这个宝贝构造函数跟构造函数有着微妙的关系吧?是的!

拷贝构造函数的概念:
  • 如果⼀个构造函数的第⼀个参数是⾃⾝类类型的引⽤,且任何额外的参数都有默认值,则此构造函数也叫做拷⻉构造函数,也就是说拷⻉构造是⼀个特殊的构造函数。(一般用ct修饰)

当然,作为一个特殊的默认成员函数,同样也符合一下构造函数的特性:

  • 拷贝构造函数是构造函数的⼀个重载。
  • 拷贝构造函数的第⼀个参数必须是类类型对象的引用,使用传值方式编译器直接报错(否则就会无限递归调用)
  • 拷贝构造函数也可以多个参数,但是第⼀个参数必须是类类型对象的引用,后⾯的参数必须有缺省值。

代码实现如下:

代码语言:javascript代码运行次数:0运行复制
class Date
	 {
public:
	 Date(int year = 1, int month = 1, int day = 1)
		 {
		 _year = year;
		 _month = month;
		 _day = day;
		 }
	
		 // 编译报错:error C2652: “Date”: ⾮法的复制构造函数: 第⼀个参数不应是“Date”
		 //Date(Date d)
		 Date(ct Date & d)
	{
	     _year = d._year;
	     _month = d._month;
	     _day = d._day;
	}
		Date(Date* d)
	{
		_year = d->_year;
		_month = d->_month;
		_day = d->_day;
	}
	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

int main() {
	Date d1(2024, 12, 22);
	//另外一种写法:d1(d2)
	Date d2 = d1;

	d1.Print();
	d2.Print();
	return 0;
}

运行结果:

运行结果就成功地将d1的值拷贝给d2啦!

当然,这里肯定还有一个问题:

为啥一定要使用引用传参呢?传值传参会怎么样吗?

那就让我们来验证一下:

运行结果:

简单来说,就是没有使用引用传参的话,就会形成无限递归传参,类似于套娃

而且,如果不需要改变参数,建议把ct加上!

代码如下:

运行结果:

这才是正确的用法,否则就会引起编译器报错,奔溃.....

记住,只要你不需要改变函数体内容,就必须把ct加上(别问为什么,因为跟我说一定要加上的人也没有说为什么)

默认的拷贝构造函数:

这里的默认拷贝构造函数就跟前面的构造函数和析构函数有所不同了

  • C++规定自定义类型对象进行拷贝行为必须调用拷贝构造,所以这里自定义类型传值传参和传值返回都会调用拷贝构造完成。
  • 若未显式定义拷贝构造,编译器会自动生成拷贝构造函数。⾃动⽣成的拷贝构造对内置类型成 员变量会完成值拷贝/浅拷贝(⼀个字节⼀个字节的拷贝),对⾃定义类型成员变量会调用他的拷贝构造。

代码实现如下:

代码语言:javascript代码运行次数:0运行复制
class Date
	 {
public:
	 Date(int year = 1, int month = 1, int day = 1)
		 {
		 _year = year;
		 _month = month;
		 _day = day;
		 }
	
		 // 编译报错:error C2652: “Date”: ⾮法的复制构造函数: 第⼀个参数不应是“Date”
		 //Date(Date d)
	//	 Date(ct Date& d)//使用引用传参
	//{
	//     _year = d._year;
	//     _month = d._month;
	//     _day = d._day;
	//}
		/*Date(Date* d)
	{
		_year = d->_year;
		_month = d->_month;
		_day = d->_day;
	}*/
	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

int main() {
	Date d1(2024, 12, 22);
	//另外一种写法:d1(d2)
	Date d2 = d1;

	d1.Print();
	d2.Print();
	return 0;
}

运行结果:

相比于构造函数和析构函数,拷贝构造函数对内置函数和自定义函数都会进行处理

对于默认的拷贝构造函数,我们也不是完全就使用默认的,比如Stack类的,我们就需要自己实现拷贝,否则如果使用Stack st1拷贝出的Stack st2会指向同一个开辟的内存空间,这样就会导致析构指向的空间两次!

这样也就会导致程序报错,奔溃.....

以上就是对于拷贝构造函数的深入剖析

有问题希望佬们及时指出哦~

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。 原始发表:2025-01-21,如有侵权请联系 cloudcommunity@tencent 删除c++date编译器对象函数

#感谢您对电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格的认可,转载请说明来源于"电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格

本文地址:http://www.dnpztj.cn/biancheng/1143578.html

相关标签:无
上传时间: 2025-07-19 09:27:30
留言与评论(共有 18 条评论)
本站网友 牡丹江电影院
22分钟前 发表
⾮法的复制构造函数
本站网友 艺术品市场
21分钟前 发表
类似于套娃而且
本站网友 神暮
17分钟前 发表
所以这里自定义类型传值传参和传值返回都会调用拷贝构造完成
本站网友 牙齿整容
20分钟前 发表
int day = 1) { _year = year; _month = month; _day = day; } // 编译报错:error C2652
本站网友 公积金还贷款计算器
18分钟前 发表
代码实现如下:代码语言:javascript代码运行次数:0运行复制class Date { public
本站网友 知了的营养价值
21分钟前 发表
⾮法的复制构造函数
本站网友 徐家汇教堂
8分钟前 发表
int month = 1
本站网友 电脑安全模式进不去
15分钟前 发表
使用传值方式编译器直接报错(否则就会无限递归调用) 拷贝构造函数也可以多个参数
本站网友 三井
2分钟前 发表
编译器会自动生成拷贝构造函数
本站网友 罗山路
10分钟前 发表
就必须把ct加上(别问为什么
本站网友 java培训ujiuye
25分钟前 发表
且任何额外的参数都有默认值
本站网友 大众电影院
22分钟前 发表
且任何额外的参数都有默认值
本站网友 苏州二手房
16分钟前 发表
但是第⼀个参数必须是类类型对象的引用
本站网友 股票诈骗
7分钟前 发表
编译器会自动生成拷贝构造函数
本站网友 夜交藤的功效与作用及禁忌
13分钟前 发表
和对应的析构函数进行清理
本站网友 干燥综合征
18分钟前 发表
分享自作者个人站点/博客
本站网友 成都阳痿
20分钟前 发表
奔溃.....记住