深浅拷贝

浅拷贝:

对于String类的拷贝构造函数或operator=函数来说:
当用一个对象拷贝构造函数或赋值给另一个String对象时,其实就是将这个对象里的指针的值赋值给另一个对象里的指针,
而此时会使得两个指针指向同一块空间,这就产生了“浅拷贝”;
分析问题:
两个或两个以上指针指向同一块空间,这个内存就会被释放多次;
另一方面,当两个指针指向同一块空间时,一旦一个指针修改了这块空间值,另一个指针指向的空间的值也会被修改
例如:string s1(“hello”);string s2(s1);此时s1,s2里面的指针就会指向同一块空间,当出了作用域,s2先调用析构函数,即该空间被释放,
接下来调用s1析构函数,也会去释放这块空间,释放一块已经被释放的空间;

解决办法:1)深拷贝

                 对于拷贝构造函数来说,s2先开一块和s1一样大的空间;对于赋值运算符重载函数来说,s2已经存在,则必须先释放s2的空间然后让s2

开辟与s1一样大的空间;
然后让s2指向这块新开辟的空间,然后后让s1里面的数据拷贝至s2指向的空间中

//拷贝构造的传统写法      
      String(const String& s)
      {
           _str = new char[strlen(s._str) + 1];  //开空间
           strcpy(_str, s._str);   //拷数据
      }

     //赋值的传统写法
      String& operator=(const String& s)   //必须要返回引用,为了连续的赋值
      {
           if (this != &s)
           {
                 delete[] _str;
                 _str = NULL;
                 _str = new char[strlen(s._str) + 1];
                 strcpy(_str, s._str);
           }
           return *this;
      }
 
//拷贝构造的现代写法      
      String(const String& s)
           :_str(NULL)  
      {
           String tmp(s._str);   //调用构造函数,则tmp就是我们需要的

           swap(_str, tmp._str);   //将_str与tmp的_str指向的空间进行交换,tmp._str就会指向_str的空间,出了这个作用域,tmp就会调用析构函数,但是tmp里面的_str值可能不确定,所以在初始化列表中将_str置空,这样tmp._str=NULL
      }

     //赋值的现代写法
      String& operator=(const String& s)
      {
           if (this != &s)
           {
                 String tmp(s._str);    //调用构造函数
                 swap(_str, tmp._str);   //tmp是局部对象,出了这个作用域就会调用析构函数,就会将tmp里面的指针指向的空间释放掉,
           }
           return *this;
      }

2)引用计数的写时拷贝

1.常用场景:
①有时会多次调用拷贝构造函数,但是拷贝构造的对象并不会修改这块空间的值;
②如果采用深拷贝,每次都会重复的开空间,然后拷数据,最后再释放这块空间,这会花费很大的精力。
③我们想到浅拷贝不用重复的开空间,但是会有问题;为了解决释放多次的问题可以采用引用计数,当有新的指针指向这块空间的时候,我们可以增加引用计数,当这个指针需要销毁时,就将引用计数的值减1,当引用计数的值为1时才去释放这块空间;
④当有一个指针指需要修改其指向空间的值时,才去开一块新的空间(也就是写时拷贝);
⑤这相当于一个延缓政策,如果不需要修改,则不用开新的空间,毕竟开空间需要很大的消耗。
⑥引用计数解决了空间被释放多次的问题,写时拷贝解决了多个指针指向同一块空间会修改的问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

记得多喝热水…

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

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

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

打赏作者

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

抵扣说明:

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

余额充值