您的位置:首页 > 编程语言 > C语言/C++

[置顶] 【C++】 浅析深浅拷贝

2016-05-26 12:25 295 查看
  C++中深拷贝和浅拷贝的问题是很值得我们注意的知识点,如果编程中不注意,可能会出现疏忽,导致bug。本文就详细讲讲C++深浅拷贝的种种。
  我们知道,对于一般对象:
) // +1是为了避免空字符串导致出错
    {
        strcpy(_str , str);
    }
    
    // 浅拷贝
    String(const String& s)
        :_str(s._str)
    {}
    
    ~String()
    {
        if(_str)
        {
            delete[] _str;
            _str = NULL;
        }
        cout<<]运行结果:



我们发现,编译通过了,但是崩溃了 =  =ll ,这就是浅拷贝带来的问题。

   事实是,在对象拷贝过程中,如果没有自定义拷贝构造函数,系统会提供一个缺省的拷贝构造函数,缺省的拷贝构造函数对于基本类型的成员变量,按字节复制,对于类类型成员变量,调用其相应类型的拷贝构造函数。原型如下:String(const String& s)
     {}
但是,编译器提供的缺省函数并不是十全十美的。

      缺省拷贝构造函数在拷贝过程中是按字节复制的,对于指针型成员变量只复制指针本身,而不复制指针所指向的目标--浅拷贝。

用图形象化为:




  在进行对象复制后,事实上s1、s2里的成员指针 _str 都指向了一块内存空间(即内存空间共享了),在s1析构时,delete了成员指针 _str
所指向的内存空间,而s2析构时同样指向(此时已变成野指针)并且要释放这片已经被s1析构函数释放的内存空间,这就让同样一片内存空间出现了
“double free”
,从而出错。而浅拷贝还存在着一个问题,因为一片空间被两个不同的子对象共享了,只要其中的一个子对象改变了其中的值,那另一个对象的值也跟着改变。所以这不是我们想要的结果,同事也不是真正意义上的复制。

为了解决浅拷贝问题,我们引出深拷贝,即自定义拷贝构造函数,如下:
[code=cpp;toolbar:false">String(const String& s)
        :_str(new char[strlen(s._str) + 1])
    {
        strcpy(_str , s._str);
    }void operator=(const String& s)
   {
      if(_str != s._str)
      {
        strcpy(_str,s._str);
      }
      return *this;
   }String& operator=(const String& s)
    {
        if(_str != s._str)  
        {
            delete[] _str;
            _str = new char[strlen(s._str) + 1];
            strcpy(_str,s._str);
        }
        return *this;
    }同时,也考虑到了自己给自己赋值的情况。

  可是这样写就完善了吗?是否要再仔细思索一下,还存在问题吗?!其实我可以告诉你,这样的写法也顶多算个初级工程师的写法。前面说过,为了保证内存不泄露,我们前面 delete[]  _str,然后我们在把new出来的空间给了_str,但是这样的问题是,你有考虑过
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: