浅谈“深拷贝”与“浅拷贝”以及相应的错误如何纠正?

目录

 

区分对象的复制与对象的赋值

解析“深拷贝”与“浅拷贝”

浅拷贝

浅拷贝简介

适用情况

当程序中有指针变量时出现错误

深拷贝

深拷贝简介

适用情况

程序如下

两者不同点仅在于拷贝函数


区分对象的复制与对象的赋值

// 在定义的同时初始化被称为拷贝  
Cstudent stud1 = stud2; // 也可以写成:stud1(stud2)   
// 在定义之后初始化被称为复制  
Cstudent stud1;  
stud1 = stud2;  

 

 

解析“深拷贝”与“浅拷贝”

浅拷贝

浅拷贝简介

浅拷贝是指源对象与拷贝对象共用一份实体,仅仅是引用的变量不同(名称不同)。对其中任何一个对象的改动都会影响另外一个对象。举个例子,一个人一开始叫张三,后来改名叫李四了,可是还是同一个人,不管是张三缺胳膊少腿还是李四缺胳膊少腿,都是这个人倒霉。

适用情况

类对象的成员变量中无指针类型的变量。

当程序中有指针变量时出现错误

#include <iostream>  
using namespace std;  
#include<string>  
  
class Cstudent  
{  
private:  
    int mark;  
    char *name;  
public:  
    Cstudent(int mark, char *name)  
    {  
        int i = strlen(name);  
        this->name = new char[i + 1]; //+1是为了存储字符串的'\0'  
        memset(this->name, 0, i + 1);  
        strcpy(this->name, name);  
        this->mark = mark;  
    }  
    Cstudent(Cstudent &stud) // 拷贝构造函数形参是该类对象的引用  
    {  
        strcpy(this->name, stud.name);  
        this->mark = stud.mark;  
    }  
    ~Cstudent()  
    {  
        if (this->name)  
        {  
            delete[] this->name;  
        }  
        cout << "调用析构函数进行收尾工作" << endl;  
    }  
    void out()  
    {  
        cout << name << endl;  
    }  
};  
  
int main()  
{  
    char str[] = "超级无敌霸霸强";  
    Cstudent stud1(89, str);  
    Cstudent stud2(stud1); // 对象拷贝  
    stud2.out();  
    stud1.out();  
} 

 

错误如下:

 

为什么会出现报错呢?

因为浅拷贝与复制仅仅是复制了一下指针中的地址,编译时一般没事,但是当内存释放时就有问题了,同样的地址释放两次,那必须报错呀!

深拷贝

深拷贝简介

深拷贝是指源对象与拷贝对象互相独立,其中任何一个对象的改动都不会对另外一个对象造成影响。举个例子,一个人名叫张三,后来用他克隆(假设法律允许)了另外一个人,叫李四,不管是张三缺胳膊少腿还是李四缺胳膊少腿都不会影响另外一个人。

适用情况

对于一切情况均适用

程序如下

#include <iostream>  
using namespace std;  
#include<string>  
  
class Cstudent  
{  
private:  
    int mark;  
    char *name;  
public:  
    Cstudent(int mark, char *name)  
    {  
        int i = strlen(name);  
        this->name = new char[i + 1]; //+1是为了存储字符串的'\0'  
        memset(this->name, 0, i + 1);  
        strcpy(this->name, name);  
        this->mark = mark;  
    }  
    Cstudent(Cstudent &stud) // 拷贝构造函数形参是该类对象的引用  
    {  
        int i = strlen(stud.name);  
        this->name = new char[i + 1]; // 深拷贝使得拷贝函数不是简单的复制对象stud.name的地址,而是执行了值传递  
        strcpy(this->name, stud.name);  
        this->mark = stud.mark;  
    }  
    ~Cstudent()  
    {  
        if (this->name)  
        {  
            delete[] this->name;  
        }  
        cout << "调用析构函数进行收尾工作" << endl;  
    }  
    void out()  
    {  
        cout << name << endl;  
    }  
};  
  
int main()  
{  
    char str[] = "超级无敌霸霸强";  
    Cstudent stud1(89, str);  
    Cstudent stud2(stud1); // 对象拷贝  
    stud2.out();  
    stud1.out();  
} 

 

两者不同点仅在于拷贝函数

浅拷贝:

Cstudent(Cstudent &stud) // 拷贝构造函数形参是该类对象的引用  
    {  
        strcpy(this->name, stud.name);  
        this->mark = stud.mark;  
    }  

 

深拷贝:

Cstudent(Cstudent &stud) // 拷贝构造函数形参是该类对象的引用  
    {  
        int i = strlen(stud.name);  
        this->name = new char[i + 1]; // 深拷贝使得拷贝函数不是简单的复制对象stud.name的地址,而是执行了值传递  
        strcpy(this->name, stud.name);  
        this->mark = stud.mark;  
     }

 

我们看到在深拷贝中我们动态申请了空间用于盛放地址对应的值,是典型的值传递,变量地址之间的传递是典型的引用。我们要的是数值,地址对应的值,不是地址,要地址没什么用处!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

肥肥胖胖是太阳

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值