浅析C++中的深拷贝与浅拷贝

深拷贝与浅拷贝是C++中的一个常见概念,同时也是各个公司面试中的常考的题目之一。本人曾经有幸被腾讯的面试官问了这一问题,当时回答的感觉不是太好,因此在准备秋招之前再次对该问题进行一次总结,希望能够得到更深的理解。‘

深拷贝与浅拷贝主要是在当类中存在指针的时候会遇到问题,并且深拷贝与浅拷贝的调用情况我个人认为就是是否使用默认的拷贝构造函数的区别。例如我们定义类:

class Student
{
private:
	int num;
	char *name;
public:
	Student();
	~Student();
};

其中包含一个char*类型的指针。我们定义构造函数:


Student::Student()
{
	name = new char(20);
	cout << "Student" << endl;
 
}

为name指针分配其指向的内存

之后我们定义main函数,并分别定义两个对象,一个对象通过构造函数获得,另一个对象通过默认的拷贝构造函数获得:

int main()
{
	{// 花括号让s1和s2变成局部对象,方便测试
		Student s1;
		Student s2(s1);// 复制对象
	}
	system("pause");
	return 0;
}

我们会发现程序会报错,原因是我们调用了一次构造函数,但是却调用了两次析构函数,导致有一个对象中的char*指针没有成功释放内存,因为它在释放内存的时候其之前指向的内存已经被释放了。

原因就在于,当我们调用默认的拷贝构造函数的时候,我们会发现两个对象中的char*指针其实指向的都是同一块内存,默认拷贝构造函数拷贝了指针,但是没有拷贝指针指向的内存,这就是浅拷贝。

为了防止这种情况的发生,我们需要自己定义拷贝构造函数,函数的参数为该类型的一个对象,在拷贝构造函数中为对象中的指针分配新的内存,这样就能够解决之前的问题,也就是我们平时所说的深拷贝。

Student::Student(const Student &s)
{
	name = new char(20);
	memcpy(name, s.name, strlen(s.name));
	cout << "copy Student" << endl;
}

需要注意的是,拷贝构造函数调用的地方有很多,不仅仅是我们在主动拷贝对象的时候,例如还有在函数的传参过程中,如果我们直接传入对象作为参数而不是对象的引用,则会调用拷贝构造函数,同理函数的对象返回值也会调用拷贝构造函数,这些都是我们在写程序的时候应该注意的地方。

参考博客:https://blog.csdn.net/caoshangpa/article/details/79226270

设计并实现一个动态整型数组类Vect,要求: (1)实现构造函数重载,可以根据指定的元素个数动态创建初始值为0的整型数组,或根据指定的内置整型数组动态创建整型数组。 (2)设计拷贝构造函数和析构函数,注意使用深拷贝。 (3)设计存取指定位置的数组元素的公有成员函数,并进行下标越界,若越界则输出“out of boundary”。 (4)设计获取数组元素个数的公有成员函数。 (5)设计用于输出数组元素的公有成员函数,元素之间以空格分隔,最后以换行符结束。 在main函数按以下顺序操作: (1)根据内置的静态整型数组{1,2,3,4,5}构造数组对象v1,根据输入的整型数构造数组对象v2。 (2)调用Vect的成员函数依次输出v1和v2的所有元素。 (3)输入指定的下标及对应的整型数,设置数组对象v1的指定元素。 (4)根据数组对象v1拷贝构造数组对象v3。 (5)调用Vect的成员函数依次输出v1和v3的所有元素。 设计并实现一个动态整型数组类Vect,要求: (1)实现构造函数重载,可以根据指定的元素个数动态创建初始值为0的整型数组,或根据指定的内置整型数组动态创建整型数组。 (2)设计拷贝构造函数和析构函数,注意使用深拷贝。 (3)设计存取指定位置的数组元素的公有成员函数,并进行下标越界,若越界则输出“out of boundary”。 (4)设计获取数组元素个数的公有成员函数。 (5)设计用于输出数组元素的公有成员函数,元素之间以空格分隔,最后以换行符结束。 在main函数按以下顺序操作: (1)根据内置的静态整型数组{1,2,3,4,5}构造数组对象v1,根据输入的整型数构造数组对象v2。 (2)调用Vect的成员函数依次输出v1和v2的所有元素。 (3)输入指定的下标及对应的整型数,设置数组对象v1的指定元素。 (4)根据数组对象v1拷贝构造数组对象v3。 (5)调用Vect的成员函数依次输出v1和v3的所有元素。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值