C++深拷贝和浅拷贝

深拷贝和浅拷贝 发生的时间就是在赋值的时候
类似int A;int B; A=B 的时候
我们已经知道在C语言的时候 操作char *需要memcpy strcpy这样的函数不能直接等
但是结构体呢?这个时候你用memcpy就是深拷贝 而你用=就是浅拷贝

系统默认的就是浅拷贝 
你要自己深拷贝的话 就自己写 拷贝构造函数 他是构造函数中的 一员 就在赋值时候调用 用一个去初始化另外一个

开始测试
准备一个基础的代码:

#include <iostream>
using namespace std;
class Person {
public:
	void setAge(int a) { age = a; }
	void setName(char *n) { name = n; }
private:
	int age;
	char *name;

};
int main()
{
	Person tom;
	tom.setAge(20);
	char c[10] = { "TOM" };
	tom.setName(c);



	system("pause");
	return 0;
}

 

 

#include <iostream>
using namespace std;
class Person {
public:
	void setAge(int a) { age = a; }
	void setName(char *n) { name = n; }
private:
	int age;
	char *name;

};
int main()
{
	Person tom;
	tom.setAge(20);
	char c[10] = { "TOM" };
	tom.setName(c);

	Person Jack = tom;//默认拷贝构造函数--浅拷贝

	unsigned int *t = (unsigned int *)&tom;
	unsigned int *j = (unsigned int *)&Jack;

	//通过内存去看数据 地址通过unsigned int转化去拿 一个是int age 后面+1就是string的name
	printf("*t=%d\n", *t);//20
	printf("*(t+1)=%s\n", *(t + 1));//tom
	printf("*j=%d\n", *j);//20
	printf("*(j+1)=%s\n", *(j + 1));//tom

	//继续看地址!
	printf("c     =%p\n", c);
	printf("*(t+1)=%p\n", *(t + 1));
	printf("*(j+1)=%p\n", *(j + 1));
	/*
	*t=20
*(t+1)=TOM
*j=20
*(j+1)=TOM
c     =0058FBC0
*(t+1)=0058FBC0
*(j+1)=0058FBC0
	*/
	system("pause");
	return 0;
}


他的效果可以证明 这就是浅拷贝 tom jack都是执行的数组的地址 一旦数组变化 tom jack都变化

 

 

 

下面开始自己深拷贝  源码就太简单了 不要用char *表示name 那怎么做????

用数组吗???

NO!

用C++的操作

*t=10
*(t+1)=TOM
*j=10
*(j+1)=TOM
*(t+1)=01032C50
*(j+1)=01032D10
c=00BBF730



#include <iostream>
using namespace std;
class Person {
public:
	void setAge(int a) { age = a; }
	void setName(char *n) { name = n; }

	Person(int a, char *n)
	{
		age = a;
		if (NULL == n)
		{
			name = new char[1];
			name[0] = '\0';
		}
		else
		{
			name = new char[strlen(n)+1];
			memcpy(name,n,strlen(n)+1);
		}
	}
	~Person() {
		delete[]name;
	}
	Person(const Person &orga)
	{
		age = orga.age;
		name = new char[strlen(orga.name) + 1];
		memcpy(name, orga.name, strlen(orga.name) + 1);
	}

private:
	int age;
	char *name;

};
int main()
{
	char c[10] = { "TOM" };
	Person tom(10,c);

	//Person Jack(tom);//拷贝构造函数--深拷贝Person(const Person &orga)
	Person Jack = tom;//拷贝构造函数--深拷贝Person(const Person &orga)
	unsigned int *t = (unsigned int *)&tom;
	unsigned int *j = (unsigned int *)&Jack;

	//通过内存去看数据 地址通过unsigned int转化去拿 一个是int age 后面+1就是string的name
	printf("*t=%d\n",     *t);//20
	printf("*(t+1)=%s\n", *(t+1));//tom
	printf("*j=%d\n",     *j);//20
	printf("*(j+1)=%s\n", *(j + 1));//tom

	//继续看地址!

	printf("*(t+1)=%p\n", *(t + 1));
	printf("*(j+1)=%p\n", *(j + 1));
	printf("c=%p\n",       c);
	system("pause");
	return 0;
}



 

此时完全分开 彼此不干扰了

也就是深拷贝是重新做内存 而浅拷贝是修改指针指向同一个内存

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
回答: 在C++中,拷贝拷贝是两种不同的拷贝方式。拷贝是简单的赋值拷贝操作,即将一个对象的值赋给另一个对象。这种拷贝方式只是复制了指针的地址,而没有重新申请内存空间。而拷贝则是在堆内重新申请空间进行拷贝操作,即重新分配内存并将原对象的值复制到新的内存空间中。\[1\] 拷贝可能会带来一些问题,特别是当属性是在堆区开辟的时候。因为拷贝只是复制了指针的地址,当原对象和拷贝对象同时指向同一块内存时,如果其中一个对象释放了内存,另一个对象仍然指向已经释放的内存,会导致程序崩溃。为了避免这个问题,我们需要提供自己的拷贝构造函数,进行拷贝操作,即重新申请内存并复制值。同时,在析构函数中需要释放申请的内存。\[1\] 举个例子来说明拷贝拷贝的区别。假设有一个Student类,其中包含一个指向字符串的指针m_name。在拷贝中,我们会重新申请一块和原对象的字符串大小相同的内存,并将原对象的字符串复制到新的内存中。而在拷贝中,只是简单地复制指针的地址,导致两个对象指向同一块内存。当原对象被销毁时,新对象仍然指向已经释放的内存,可能会导致程序出错。\[2\]\[3\] #### 引用[.reference_title] - *1* [c++拷贝拷贝](https://blog.csdn.net/qq_43611366/article/details/125204856)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [C++拷贝拷贝](https://blog.csdn.net/m0_59052131/article/details/127498856)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值