【c++】深拷贝和浅拷贝简单理解

1.浅拷贝
浅拷贝:多个指针指向同一段内存,出现一处指针修改数据,其它指针的数据也发生改变。

例如:

int main()
{
   char buf[100];
   char* strArr[4];//长度为4的字符指针数组,分别指向4个字符串
   for (int i = 0; i <4 ; i++)//从键盘获取4个字符串
   {
      cin >> buf;
      strArr[i] = buf;
   }
   for (int i = 0; i < 4; i++)//把4个字符串输出到屏幕
      cout << strArr[i] << " ";

   return 0;
}

在键盘中输入4个单词:Apple Banana Orange Peach
但是输出的结果却是:Peach Peach Peach Peach

原因如图:

假设buf的地址为200。第一次从键盘读取Apple,并把200这个地址赋值给strArr[0]。
第二次从键盘读取Banana,并把200这个地址赋值给strArr[1],注意这个地方的问题,由于buf这段内存只有一个,第二次赋值会把第一次的Apple覆盖。
第三次从键盘读取Orange,并把200这个地址赋值给strArr[2],但这时Orange把前面的输入覆盖了。
第四次从键盘读取Pear,并把200这个地址赋值给strArr[3]。但这是Pear把前面的输入覆盖了。
最后输出时strArr[0]到strArr[3]都去地址200处取字符串,就全部都是"Pear"。


这是一个典型的浅拷贝,多个指针指向同一段内存造成的。

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;

//深拷贝
//下面程序,从键盘获取4个字符串,然后输出到屏幕
int main()
{
    char buf[100];
    char* strArr[4];//长度为4的字符指针数组,分别指向4个字符串
    for (int i = 0; i < 4; i++)//从键盘获取4个字符串
        {
            cin >> buf;
            //strArr[i] = buf;//这是浅拷贝
            //下面的是深拷贝
            strArr[i] = (char*)malloc(strlen(buf) + 1);//1.创建单独的内存
            strcpy(strArr[i],buf);//2.复制数据
        }

    for (int i = 0; i < 4; i++)//把4个字符串输出到屏幕
        cout << strArr[i] << " ";

    //最后需要释放动态内存
    for (int i = 0; i < 4; i++)
        free(strArr[i]);
    return 0;
}

1.2 面向对象的浅拷贝(类)

下面是一个有问题的类(StringBad类的简化版),只是为了演示浅拷贝的问题

class CStr
{
private:
char* str;//字符串指针
public:
CStr(const char* s)//构造函数,通过s构造一个CStr类对象
{
    str = new char[strlen(s) + 1];//动态创建内存
    strcpy(str,s);//把s的内容复制到str
}
void set(const char* s)//修改字符串的值
{
    delete[]str;//释放原来的内存
    str = new char[strlen(s) + 1];//动态创建内存
    strcpy(str, s);//把s的内容复制到str
}
void show()const
{
    cout << str << endl;
}
};

int main()
{
    CStr s1{"有趣的编程"};
    s1.show();//输出s1的内容

    CStr s2 = s1; //把s1赋值给s2
    s2.show();//输出s2的内容

    s2.set("好好学习,天天向上");//修改s2的值
    s2.show();//输出s2的内容
    s1.show();//再输出s1的内容

    return 0;
}

创建一个对象s1,并初始化为"有趣的编程";
创建另一个对象s2,并把s1赋值给s2;
输出s2的内容,这是是s1赋值的值,这是正确的;
修改s2的内容,将其改为"好好学习,天天向上";
输出s2的内容,是修改后的值"好好学习,天天向上",这是正确的;
输出s1的值,应该是"有趣的编程",但实际输出的却是"好好学习,天天向上",这是错误的。
错误的原因也是浅拷贝造成的,具体原因如下图:

2.深拷贝
深拷贝,即为每个指针创建一个单独的内存,然后再复制数据。
2.1 面向过程的深拷贝
把前面的浅拷贝程序进行适当的修改,如下:

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;

//深拷贝
//下面程序,从键盘获取4个字符串,然后输出到屏幕
int main()
{
    char buf[100];
    char* strArr[4];//长度为4的字符指针数组,分别指向4个字符串
    for (int i = 0; i < 4; i++)//从键盘获取4个字符串
        {
            cin >> buf;
            //strArr[i] = buf;//这是浅拷贝
            //下面的是深拷贝
            strArr[i] = (char*)malloc(strlen(buf) + 1);//1.创建单独的内存
            strcpy(strArr[i],buf);//2.复制数据
        }

    for (int i = 0; i < 4; i++)//把4个字符串输出到屏幕
        cout << strArr[i] << " ";

    //最后需要释放动态内存
    for (int i = 0; i < 4; i++)
        free(strArr[i]);
    return 0;
}

从上面的程序能够正常的输出。
第12行,为每个字符串创建单独的内存,用于存放数据。
第13行,将数据从buf复制到新创建的内存。
第20,21行,释放每个字符串单独创建的内存,否则出现内存泄漏。

2.2 面向对象的深拷贝(类)
这个过程比较复杂,下面的String类针对浅拷贝的问题,重新实现了拷贝构造函数和赋值=运算符函数。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值