解释深浅拷贝问题,并且使用代码示例描述

       深拷贝,就是对数据成员逐一赋值。但是如果类中含有指针类型数据,则这种按数据成员逐一赋值的方法将会产生错误。

1、浅拷贝例子

  1 #include <iostream>
  2 #include <cstring>
  3 
  4 using namespace std;
  5 
  6 class Student{
  7     char *name;
  8     float score;
  9 public:
 10     Student(char *name1,float score1);
 11     ~Student();
 12 };
 13     
 14 Student::Student(char *name1,float score1)
 15 {
 16     name = new char[strlen(name1)+1];
 17     if(0 != name)
 18     {
 19         strcpy(name,name1);
 20         score = score1;
 21     }
 22     cout << "构造" << " " << name1 << endl;
 23 }   
 24     
 25 Student::~Student()
 26 {
 27     cout << "析构" << " " << name << endl;
 28     name[0] = '\0';
 29     delete []name;
 30 }
 31 
 32 int main(int argc,char *argv[])
 33 {   
 34     Student stu1("张三",99);
 35     Student stu2 = stu1;
 36 
 37     return 0;
 38 }


程序运行结果为:

        构造 张三
        析构 张三
        析构 
        free(): double free detected in tcache 2
        已放弃 (核心已转储)

 

2、代码解析

       程序开始运行,创建对象stu1时,调用构造函数,用运算符new从内存中动态分配一块空间,字符指针name指向这个内存块,如图所示,这时产生第1行输出“构造 张三”。执行语句"Sudent stu2=stu1;"时,因为没有定义拷贝构造函数,于是就调用默认的拷贝构造函数,把对象stu1的数据成员(字符指针name和浮点数score )逐个复制到stu2的对应数据成员中,使得stu2与stu1完全一样,但并没有新分配内存空间给stu2,如图所示。主程序结束时,对象逐个被撤销,先撤销对象stu2,第1次调用析构函数,用运算符delete释放动态分配的内存空间,并同时得到第2行输出“析构 张三”,如图所示;撤销对象stu1时,第2次调用析构函数,因为这时指针name所指的空间已被释放,所以第3行输出显示“析构 葺葺葺葺”,字符串“张三”被随机字符取代;当执行析构函数中的语句"delete []name;"时,企图释放同一空间,从而导致了对同一内存空间的两次释放,这当然是不允许的,必然引起运行错误。
 

3、解决方案

       显示的定义一个自定义的拷贝构造函数,使之不但复制数据成员,而且还为对象stu1和stu2分配各自的内存空间,这就是深拷贝。

  1 #include<iostream>
  2 #include<cstring>
  3 
  4 using namespace std;
  5 
  6 class product{
  7 public:
  8     product(char *n,int p,int q);
  9     product(const product &p );
 10     ~product();
 11     void buy(int money);
 12     void get()const;
 13 private:
 14     char *name;
 15     int price;
 16     int quantity;
 17 };

 18 product::product(char *n,int p,int q)
 19 {
 20     name = new char[30];
 21     strcpy(name,n);
 22     price = p;
 23     quantity = q;
 24 }   

 25 product::product(const product &p)
 26 {
 27     name = new char[strlen(p.name)+1];
 28     strcpy(name,p.name);
 29     price = p.price;
 30     quantity = p.quantity;
 31 }   
 32     
 33 product::~product()
 34 {
 35     name[0] = '\0';
 36     delete []name;
 37 }   
 38     
 39 void product::buy(int money)
 40 {
 41     int num;
 42     num = money/price;
 43     cout << "买" << " " << num << " " << "个产品" << endl;
 44 }   
 45     
 46 void product::get()const
 47 {
 48     cout << quantity << endl;
 49 }   
 50     
 51 int main()
 52 {
 53    product pr1("张三",25,100);
 54    product pr2(pr1);
 55    product pr3 = pr1;
 56    pr2.buy(520); 
 57    pr3.get();
 58    
 59    return 0;
 60 }

        对比上一个代码例子,多了一个关于product(const product &p );的构造函数定义。

输出结果如图所示:

 
————————————————
版权声明:本文为CSDN博主「Samuel Chen」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_42442875/article/details/95471170

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值