String类之 深拷贝

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_39412582/article/details/81515037

上篇博客我们说浅拷贝存在同一块资源被多次释放的问题,那么这篇博客就是给浅拷贝擦屁股,解决它遗留下来的问题。

解决这个问题,我们可以考虑单独给 s2 开辟一块空间,只将 s1 里的内容拷贝到 s2。
看一看我们代码是怎么实现的吧:

class String
{
public:
    String(const char* pStr = "")
    {
        if (NULL == pStr)         //保证这个字符串里面至少有一个大小的空间
        {
            _pStr = new char[1];
            *_pStr = '\0';
        }
        else
        {
           //如果该字符串不空,重新开辟一块空间,将原来字符串里的内容拷贝到新空间中
            _pStr = new char[strlen(pStr) + 1];
            strcpy(_pStr, pStr);
        }
    }
    //普通版版本
    String(const String& s)  //拷贝构造函数,这里没有判断字符串是否为空,是因为它不可能为空
        :_pStr(new char[strlen(s._pStr) + 1])
    {
        strcpy(_pStr, s._pStr);
    }
    //要做到赋值运算符重载,首先当然是开辟一块新空间来保存待拷贝的内容,然后将旧空间元素拷贝到新空间,紧接着释放掉旧空间,指向新空间,这样复制拷贝整个过程就结束了
    String& operator=(const String& s)
    {
        if (this != &s)     //首先判断是不是自己给自己赋值
        {
            //法一:如果内存开辟失败不会影响原来的空间
            char* pTemp = new char[strlen(s._pStr) + 1];  //申请新空间    
            strcpy(s._pStr, _pStr);  //拷贝元素    
            delete[] _pStr;  //释放旧空间   
            _pStr = pTemp;   //使用新空间

            //法二:上来就释放就空间,倘若新空间开辟失败会影响原来的空间
            delete[] _pStr;
            _pStr = new char[strlen(s._pStr) + 1];
            strcpy(_pStr, s._pStr);
        }
        return *this;
    }
    ~String()
    {
        if (_pStr)
        {
            delete[] _pStr;
            _pStr = NULL;
        }
    }
private:
    char* _pStr;
};
void TestFunc()
{
    String s1("hello");
    String s2(s1);  


    String s3;
    s3 = s1;
}
int main()
{
    TestFunc();
    return 0;
}

我们来看看结果怎么样:
这里写图片描述
除了函数作用域,调用析构函数,里面内容全部被清空,没有问题对不对。
那有人就会问有没有更简单的方法来实现这个功能呢?当然有了
这次我给出一个简洁版的代码:

//第一种
String& operator=(const String& s)   
    {
        if (this != &s)
        {
        //既然要拷贝元素,那我直接给一个String类调用拷贝构造函数,然后在进行交换那岂不是万事大吉,代码很简洁,还不会出错
            String strTemp(s._pStr);  
            swap(_pStr, strTemp._pStr);
        }
        return *this;
    //第二种
    String& operator=(const String& s) 
    {
        String strTemp(s);
        swap(_pStr, strTemp._pStr);
        return *this;
    }
    //第三种
    String& operator=(String s)  
    {
        swap(_pStr, s._pStr);
        return *this;
    }

这里写图片描述
经检验,上面三种方法都没毛病,读者想用哪种就用哪种,看自己能理解那种了。

猜你喜欢

转载自blog.csdn.net/qq_39412582/article/details/81515037