别拿浅拷贝不当拷贝

我们知道C++中类里的成员函数中构造函数和拷贝构造都是值拷贝,所以地址也是值拷贝,也就是多个对象用到了同样的一块地址,例如:

#include <iostream>using namespace std;class String{public:    String(char* str)    :_str(new char[strlen(str)+1])    {        strcpy(_str,str);    }    //拷贝构造函数    ~String()    {        delete this->_str;    }private:    char* _str;};void Test(){    String s1("abcdef");    String s2(s1);}int main(){    Test();    return 0;}

上面的程序中我省略掉了拷贝构造函数,系统会自动生成一个,就是值拷贝,也是浅拷贝,因此s1和s2中字符串指针指向了由new开辟出来的同一块地址,那么当出了Test()的作用域时会调用两次析构函数,那么也就是会把同一块内存释放两次,系统毫无疑问就会崩溃掉,那么解决这个问题的方法就可以用深拷贝,开辟出同样大小的一块空间,再将字符串的内容给拷贝过去。

但是,就用浅拷贝可不可以解决上述问题呢?看如下的程序:

#include <iostream>using namespace std;class String{public: String(char* s = "")  :_str(new char[strlen(s)+5]) {  *((int*)_str) = 1;  //初始化计数器个数为1  strcpy(_str+4,s); } String(String& str) {  _str = str._str;  ++(*((int*)_str));  //每当增加一个对象使用这块内存时计数器就++ } ~String() {  if((--(*((int*)_str))) == 0)//释放内存时只有当计数器减完后为0时才可以释放  {   delete[] _str;  } } String& operator=(String& str) {  if(--(*((int*)_str)) == 0)//只有确保没有其他对象在使用这块空间时才可以将原来的空间释放  {   delete[] _str;  }  _str = str._str;  ++(*((int*)_str));  return *this; }private: char* _str;};void Test1(){ String s1("abcd"); String s2(s1); String s3 = s2; String s4("efgh"); String s5; s5 = s4;}int main(){ Test1(); return 0;}

在上面的程序中注意到在构造函数的初始化类表中我new出了多4个字节的空间,那这4个空间是用来干什么的呢?

在用new[ ]的时候,如果用sizeof检查其字节,会发现开辟出的大小会多出4个字节,这四个字节在开辟出的空间首部,用来存储数组元素的个数,从而配合delete来释放空间。

因此,我多开辟出的4个空间就也是用来存放指向同一块空间的对象的个数的。

这样就可以在需要重复使用相同的内容时节省内存空间也避免出现内存泄露或者程序崩溃。

本文出自 “敲完代码好睡觉zzz” 博客,请务必保留此出处http://2627lounuo.blog.51cto.com/10696599/1719361

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值