C++里面的深拷贝和浅拷贝

//拷贝有两种:深拷贝和浅拷贝



 

//1.结构体中的深拷贝和浅拷贝




/*
  浅拷贝:编译器仅仅拷贝了结构体的值,而没有创建新的内存空间,而是共享同一块内存空间
。当结构体成员中含有buf的时候,拷贝之后释放内存就不会出现问题,但是如果结构体中含有指针变量时,
  编译器就只会拷贝指针变量,而对应
  的,内存空间却不会缺,不再多分配。

深拷贝:
    编译器会为拷贝的对象分配一定的内存空间

 

 

 
  1. #include <iostream>

  2. using namespace std;

  3. /*

  4. struct Teacher

  5. {

  6. string name;

  7. int age;

  8.  
  9. }Teacher;

  10.  
  11.  
  12. int main()

  13. {

  14.  
  15. struct Teacher t1={"cang",18};

  16. struct Teacher t2={"li",20};

  17. t2=t1;//浅拷贝,没有为t2创建内存空间

  18. cout<<"age is:"<<t2.age<<"name is:"<<t2.name<<endl;

  19. return 0;

  20. }

  21.  
  22. */


 

 

 
  1. //上面的结构体可以直接使用等于号进行赋值操作;

  2. /*

  3. #include <iostream>

  4. #include <stdio.h>

  5. using namespace std;

  6. struct Teacher

  7. {

  8. int id;

  9. char sex;

  10. const char *p;

  11.  
  12. }Teacher;

  13.  
  14.  
  15. int main()

  16. {

  17. struct Teacher t1, t2;

  18. //const 修饰加上,因为const 存储在常量区,不能被修改,通过指针修改比较危险

  19. //所以通过前面加上const之后,警告消失

  20. const char *str ="i am string";

  21. t1.id = 345;

  22. t1.sex = 'y';

  23. //const 修饰的变量只能用const修饰的变量来接收

  24. t1.p = str;

  25. t2=t1;

  26. printf("t2: %d,%c,%s\n",t2.id,t2.sex,t2.p);

  27. //此处打印出来的丢值都是一样的,说明并没有将内容复制一块给新指针,

  28. //只是让新的指针指向原来的那个地址,这就相当于,指针在这个过程中只赋值了地值

  29. //而不是内容

  30. printf("s1 ptr:%p,p2 ptr:%p\n",t1.p,t2.p);

  31.  
  32. //这里没有进行运算符重载,所以会出现operator+();

  33. cout<<"t2:"<<t2.id<<t2.sex,t2.p<<endl;

  34. cout<<"t1.p:"<<(void *)t1.p<<"t2.p"<<(void *)t2.p<<endl;

  35.  
  36. return 0;

  37. }

  38.  
  39.  
  40. */


 

//上面函数的原理:
/*在拷贝过程中,如果没有自定义拷贝构造函数,系统会提供一个缺省的拷贝构造函数
 缺省的拷贝构造函数对基本类型的成员变量,按字节赋值,对于类型的成员变量,调用其相应类型的拷贝构造函数
 。但是注意缺省的构造函数确实这样的:缺省拷贝构造函数在拷贝过程中是按自己复制的,对于指针变量只赋值指针本身,
 而不赋值指针所指项目标======浅拷贝
 
 这就是问题产生的原因:  ***********浅拷贝出现了****************************************************

 在对对象进行赋值之后,事实上S1,S2的成员都指向同一块内存空间(内存共享)在t1析构时,delete了成员指针所指向的内存空间
 而t2被析构时同样指向了(此时这个指针已经变成了野指针)并且要释放这篇已经被t1析构了的内存空间。在同一片空间出现两次释放
 自然会出现段错误;
 由于内存共享,只要一个子对象改变了其中的值,另一个对象的值也就改变了。

 怎么实现深拷贝:
    自定义拷贝构造函数


 */
 

 
  1. #include <iostream>

  2. #include <stdio.h>

  3. #include <string.h>

  4. using namespace std;

  5. struct Teacher

  6. {

  7. int id;

  8. char sex;

  9. char *p;

  10. //自定义拷贝构造函数,实现深拷贝

  11. Teacher operator=(Teacher & tec)

  12. {

  13. id = tec.id;

  14. sex = tec.sex;

  15. p = new char(strlen(tec.p)+1);

  16. strcpy(this->p,tec.p);

  17. return *this;

  18.  
  19. }

  20.  
  21. };

  22.  
  23. //相当于重载operator= 方法,这样还是运行,结果就变了

  24.  
  25.  
  26. int main()

  27. {

  28. struct Teacher t1, t2;

  29. //const 修饰加上,因为const 存储在常量区,不能被修改,通过指针修改比较危险

  30. //所以通过前面加上const之后,警告消失

  31. char *str ="i am string";

  32. t1.id = 345;

  33. t1.sex = 'f';

  34. //const 修饰的变量只能用const修饰的变量来接收

  35. t1.p = (char *)str;

  36. t2=t1;

  37. printf("t2: %d,%c,%s\n",t2.id,t2.sex,t2.p);

  38. printf("s1 ptr stress:%p,p2 ptr stress:%p\n",t1.p,t2.p);

  39. printf("s1 ptr:%s,p2 ptr:%s\n",t1.p,t2.p);

  40.  
  41.  
  42. return 0;

  43. }




//类和上面的结构体一致,其实可以将结构体看成一个类来处理,结构体可以有自己的构造,析构,重载运算符,
//可以简单的认为结构体是类的一种形式。


//拷贝函数有两种:深拷贝 浅拷贝

//当出现类的等号赋值时,会调用拷贝函数,在未定义的显示拷贝构造函数的情况下,系统会调用默认的拷贝函数----浅拷贝
//能够完成成员的复制

//当成员数据中没有指针时,浅拷贝是可以的,但当数据成员中有指针时,如果采用简单的浅拷贝,则两类中的两个指针指向同一个地址,
//当对象快结束的时候,会调用两次析构,而导致指针悬挂现象。所以,这时必须采用深拷贝,深拷贝与前拷贝的不同在于
//深拷贝会在堆内存中申请空间来存储数据,从而也就结局了指针悬挂的问题。简而言之,当数据成员中有指针的时候,必须要用
//深拷贝。
//建议:
//  我们在定义类或者是结构体的时候,最后都重写拷贝构造函数,避免浅拷贝;这类不宜发现但后果严重的错误产生。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值