String类的实现(深拷贝or浅拷贝)

今天,我们来实现一个字符串String的拷贝(String用来管理字符串)~具体以浅拷贝和深拷贝的形式给出~
那么问题来了?什么是浅拷贝呢?深拷贝又是什么呢?

 浅拷贝就相当于你喜欢一个人的感觉,而深拷贝相当于你爱一个人的感觉
 我们都知道say like很容易,因为可能是他/她的外表所吸引,但是,say love却很难,因为你只有深入了解了他的本质才会爱上他~

 浅拷贝:也称为位拷贝,编译器只是将指针的内容拷贝过来,导致多个对象共用一块内存空间,当其中任意对象将这块空间释放之后,其他对象再对这块空间进行操作时,就会导致程序崩溃。
 深拷贝:为了解决浅拷贝留下来的问题,采用给每个对象各自一块空间,各吃各加饭,从实质上解决问题。

那么你是想只保持在喜欢阶段呢,还是想进一步发展呢 ε=ε=ε=(~ ̄▽ ̄)~
我们直接抛代码~

“喜欢”之浅拷贝

#include<iostream>
#include<string.h>
#include<windows.h>
using namespace std;
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(s._pStr)
    {}
    ~String()
    {
        if (_pStr)
        {
            delete[] _pStr;
            _pStr = NULL;
        }
    }
private:
    char* _pStr;
};
void FunTest()
{
    String s1("hello world");
    String s2(s1);
    String s3;
    s3 = s2;
}
int main()
{
    FunTest();
    system("pause");
    return 0;
}

这里写图片描述
可以看到,s2虽然赋值成功了,但程序却崩溃了,这是为什么呢???
经过调试发现,程序在拷贝构造s2时,程序并未出现异常,但在对象析构时,在析构完s2之后,程序在析构s1时崩了,这是什么原因呢??
我们来分析一下代码~
这里写图片描述
由于s1和s2同时指向了同一块空间,程序在析构时,先析构了s2,空间释放,s1变为野指针,再析构s1时,那块空间已经不存在了,导致程序失败~
“爱”之深拷贝(各自拥有各自的空间)——普通版

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* Temp = new char[strlen(s._pStr) + 1];
            //Temp在栈上,函数结束便会释放,开辟的空间就不存在
            strcpy(Temp, s._pStr);
            delete[] _pStr;
        }
        return *this;
    }

    ~String()
    {
        if (_pStr)
        {
            delete[] _pStr;
            _pStr = NULL;
        }
    }
private:
    char* _pStr;
};

    void FunTest()
    {
        String s1("hello");
        String s2(s1);
        String s3;
        s3 = s2;
    }
int main()
{
    FunTest();
    system("pause");
    return 0;
}

“深爱”之深拷贝的简洁版

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)
    //{
    //  String temp(s._pStr);//调用构造函数
    //  swap(_pStr, temp._pStr);//把当前对象*this和临时对象temp交换
    //                           //但是当前对象是一个野指针
    //}
    //解决方法一(存在问题 有可能导致申请空间失败)
    //String(const String& s)
    //{
    //  _pStr = new char[1];//创建当前空间,里面放‘\0’
    //  String temp(s._pStr);
    //  swap(_pStr, temp._pStr);
    //}

    //解决方法二
    String(const String& s)
        :_pStr(NULL)
    {
        String temp(s._pStr);
        swap(_pStr, temp._pStr);
    }
    //赋值运算符重载(一)建议写这种
    //String& operator=(const String& s)//传参过程中无需创建临时对象
    //{
    //  if (this != &s)//判断如果不是自己给自己赋值才创建临时对象
    //  {
    //      String temp(s); // 调用拷贝构造函数
    //      swap(_pStr, temp._pStr);
    //  }
    //  return *this;
    //}
    //赋值运算符重载(二)不建议写这种
    //String& operator=(const String& s)
    //{
    //      String temp(s._pStr);//调用构造函数创建临时的
    //      swap(_pStr, temp._pStr);
    //      return *this;
    //}
    //赋值运算符重载(三)这种方式虽然也可以,但是函数在传参的过程中就构造临时对象,调用拷贝构造函数,
    String& operator=(String s)//以值传递形式传递
    {
        swap(_pStr, s._pStr);
        return *this;
    }
    ~String()
    {
        if (_pStr)
        {
            delete[] _pStr;
            _pStr = NULL;
        }
    }
private:
    char* _pStr;
};

void FunTest()
{
    String s1("hello");
    String s2(s1);
    String s3;
    s3 = s2;
}
int main()
{
    FunTest();
    system("pause");
    return 0;
}
   我想写代码同恋爱一样,如果“爱”,请“深爱”~
   代码有问题或者表述有误,希望大家多多指教:)
                 国庆快乐~
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值