C++深浅拷贝解析

Visual Studio 编译环境验证:

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <stdio.h>



using namespace std;

#define LOG(format, ...) printf(format, ##__VA_ARGS__)

class Student
{
public:
	int age;
	char * name;
	Student(){
		LOG("空参数构造函数\n");
	}

	Student(char * name) :Student(name, 99){
		cout << "一个参数构造函数 this:" << (int)this << endl;
	}
	Student(char * name, int age){
		cout << "二个参数构造函数 this:" << (int)this << endl;
		this->name = (char *)malloc(sizeof(char*)* 10);
		strcpy(this->name, name);
		this->age = age;
	}


	~Student(){
		cout << "析构函数执行 &this->name:" << (int)this->name << endl;
		free(this->name);
		this->name = NULL;
	}
	Student(const Student &stu){
		cout << "拷贝构造函数 &stu:" << (int)&stu << " this:" << (int)this << endl;
		//浅拷贝;相当于复制内存的内容,但是始终指向同一块内存空间
		//this->name = stu.name;
		//深拷贝:创建新的地址
		this->name = (char*)malloc(sizeof(char*)* 10);
		strcpy(this->name,stu.name);
		this->age = stu.age;
		cout << "拷贝构造函数 stu.name:" << (int)stu.name << " this->name:" << (int)this->name << endl; //验证为什么崩溃

	}

};


void showStudent(Student stu){
	cout << "showStudent函数:" << (int)&stu << "  " << stu.name << "," << stu.age << endl;

}//出栈 就会执行析构函数 做释放内存操作

void  main(){

        Student stu("张三",11);
	showStudent(stu);
		//结果打印:
		//二个参数构造函数 this:13892916  ——————> Student stu("张三",11);
		//拷贝构造函数 &stu : 13892916 this : 13892680 --------->showStudent(Student stu)执行的时候会将上一步 创建的stu通过拷贝构造函数重新申请一个新的stu地址
		//showStudent函数:13892680  张三, 11 -------> showStudent 拿到了新地址的stu
		//析构函数执行 &this->name : 14401392 
	showStudent(stu); // 再调用showStudent函数 也会奔溃
	getchar();//去掉此行 程序运行奔溃

//拷贝构造函数添加打印 新旧stu地址对应的name地址,打印结果:
		//二个参数构造函数 this:15727400
		//拷贝构造函数 &stu : 15727400 this : 15727164
		//拷贝构造函数 &stu : 19382768 this->name : 19382768  // 新旧stu对象的name指向的地址是相同的
		//showStudent函数:15727164  张三, 11
		//析构函数执行 &this->name : 19382768

	//多次条用showStudent 或者取掉 getchar奔溃原因:
	//多次调用showStudent当第一个showStudent出栈会执行析构函数释放name内存 第二个showStudent出栈时也会调用析构函数释放内存
	//去掉getchar main 函数出栈 释放旧地址stu的name 内存  新旧stu对象的name地址相同  情况同上 也是做了多次释放操作

//****************************************************************************************************
//添加深拷贝后调用两次showStudent打印如下:

		//二个参数构造函数 this:10025748
		//拷贝构造函数 &stu : 10025748 this : 10025500
		//拷贝构造函数 stu.name : 1229304 this->name : 1229408	//新旧stu对应的栈空间name的内存地址是不一样的
		//showStudent函数:10025500  张三, 11
		//析构函数执行 &this->name : 1229408
		//拷贝构造函数 &stu : 10025748 this : 10025500
		//拷贝构造函数 stu.name : 1229304 this->name : 1229408   //释放后重新指向的地址和上一次相同 无关紧要,因为上有个showStudent已经出栈了
		//showStudent函数:10025500  张三, 11
		//析构函数执行 &this->name : 1229408  //多次释放没有任何影响


}//出栈 旧的stu地址做释放操作 

请参考以上代码做测试。

补充一点:默认的拷贝构造函数是浅拷贝

验证方法:把重写的拷贝构造函数注释掉,打开多次调用showStudent此时运行会崩溃

所以:如果成员中都堆成员,则必须使用深拷贝

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值