C++构造函数的浅拷贝与深拷贝


前言

上期讲到构造函数,本期接着讲


本文章为初学者为巩固知识所创作,知识有限,大佬轻喷

一、编译器默认提供的构造函数

首先来看一段代码

class MyClass
{
public:
	int i;
	char c;
	string str;

};

void main()
{
	MyClass class1;

	cout << class1.i << " ";
	cout << class1.c << " ";
	cout << class1.str << " ";
	cout << endl;
}

解释一下写这段代码的原因:
首先定义一个MyClass类,
内部并没有定义任何构造函数,那么内部的变量的值是多少呢?
我们调用一下test函数

运行截图
结果可以发现,内部变量是随机值

那我们实现一个有参构造函数呢

class MyClass
{
public:
	int i;
	char c;
	string str;

	MyClass(int i, char c, string str)
	{
		;
	}
};

void test()
{
	MyClass class1;

	cout << class1.i << " ";
	cout << class1.c << " ";
	cout << class1.str << " ";
	cout << endl;
}

定义了一个有参构造函数,但内部没有任何函数实现

再次调用test函数
在这里插入图片描述
报错了
错误为MyClass没有默认构造函数
那为什么定义一个有参构造函数后就报错了呢?

在这里插入图片描述
因为在自己没有实现任何构造函数时,编译器会自己实现三个空构造函数,而当自己实现了构造函数后,就会发生变化

如何再加上这段代码

MyClass class1;	
MyClass class2(1, '2', "abc");
MyClass class3(class2);

创建对象class1时报错,class3时没有报错。

所以可见编译器提供了拷贝构造函数,没有提供无参构造函数
这种构造函数叫‘隐式构造’
当自己没有实现任何构造函数时,类会提供3种隐式构造函数
自己实现了有参构造后,类则不会提供隐式默认无参构造
当自己实现拷贝构造函数后,类不会提供任何隐式构造函数

二、浅拷贝与深拷贝

老规矩,上代码

class MyClass
{
public:
	int i;
	char c;
	string str;

	MyClass(int i, char c, string str)
	{
		this->i = i;
		this->c = c;
		this->str = str;
	}
};

void test()
{
	MyClass class1(1, 'c', "abc");
	MyClass class2(class1);

	cout << "class2内部变量为:";
	cout << "i = " << class2.i << "  ";
	cout << "c = " << class2.c << "  ";
	cout << "str = " << class2.str << "  ";
	cout << endl;
}

调用test函数
运行结果:
在这里插入图片描述
上述代码我们使用编译器提供的拷贝构造函数初始化class2,并没有任何问题

那么我们如果把成员变量存放到堆区呢

class MyClass2
{
public:
	int* arr;

	MyClass2()
	{
		arr = new int[4];
		for (int i = 0; i < 4; i++)
			arr[i] = i;
	}

	void show()
	{
		for (int i = 0; i < 4; i++)
			cout << arr[i] << " ";
		cout << endl;
	}
};

void test2()
{
	MyClass2 class1;
	MyClass2 class2(class1);
	cout << "class1 修改前 class2 内部arr数据为:";
	class2.show();
	
	for (int i = 0; i < 4; i++)
		class1.arr[i] = i + 1;
	cout << "class1 修改后 class2 内部arr数据为:";
	class2.show();
}

int main()
{
	test2();
	return 0;
}

MyClass2中arr是堆区数组,我们通过默认构造对class1进行初始化,此时class1.arr中数据为 0,1, 2, 3

再通过默认的拷贝构造对class2进行初始化,那么class2.arr中数据肯定也为 0,1, 2, 3

用下面的代码修改class1中的数据

for (int i = 0; i < 4; i++)
		class1.arr[i] = i + 1;

修改后为 1, 2, 3, 4
我们执行代码看看class2中数据为多少

在这里插入图片描述
class2 为什么也改变了呢
在这里插入图片描述

用图片来解释吧

在这里插入图片描述
编译器默认的拷贝构造执行了
class2.arr = class1.arr;
这样的操作二者指向同一块内存区域,修改class1,class2 也会改变

编译器默认的拷贝构造函数为浅拷贝
那么如何解决这种浅拷贝的问题呢

当然是自己实现拷贝构造函数啦
在这里插入图片描述

在这里插入图片描述
只要自己实现拷贝构造函数让堆区的数据也拷贝过来就行了
思路简单,直接上代码

MyClass2(MyClass2& cla)
{
	this->arr = new int[sizeof(cla.arr)];
	for (int i = 0; i < sizeof(cla.arr); i++)
		this->arr[i] = cla.arr[i];
}

执行效果:
在这里插入图片描述

OK,完了,下期写点什么好呢,简单写写运算符重载吧(反正没人看

请添加图片描述
都看到这了点个赞呗
下期再见

  • 9
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值