深浅拷贝

class String
{
public:
    String(const char *pStr = "")
    {
        /*
        方法1:
        if (NULL == pStr)
        {
            //空串
            _str = new char[1];
            *_str = '\0';
        }
        else
        {
            _str = new char[strlen(pStr) + 1];
            strcpy(_str, pStr);
        }
        */

        //方法2:
        if (pStr == NULL)
        pStr = "";
        _str = new char[strlen(pStr) + 1];
        strcpy(_str, pStr);
    }

    ~String()
    {
        if (_str)
            delete[] _str;
    }
private:
    char *_str;
};

int main()
{
    String str1("hello");
    String str2(NULL);
    String str3;

    system("pause");
    return 0;
}

浅拷贝

也称位拷贝,编译器只是将对象中的值采用基本类型值复制的方式拷贝过来,如果对象中管理资源,最后就会导致多个对象共享同一份资源,当一个对象销毁时就会将该资源释放掉,而此时另一些对象不知道该资源已经被释放, 以为还有效,所以当继续对资源进行操作时,就会发生访问违规

void Test()
{
    String s1("hello");
    //拷贝构造
    String s2(s1);

    String s3("world");
    //赋值运算符重载
    s1 = s3;
}

当类里面有指针对象时,拷贝构造和赋值运算符重载只进行值拷贝,两个对象共用同一块空间,对象销毁时程序会发生内存访问违规

//系统默认的拷贝构造和赋值运算符重载(反例)------程序崩溃
    String(const String& s)
        :_str(s._str)
    {}

    String &operator=(const String& s)
    {
        _str = s._str;
        return *this;
    }

深拷贝

解决方法,用户给出自己的拷贝构造和赋值运算符重载

    String(const String& s)
        :_str(new char[strlen(s._str) + 1])
    {
        strcpy(_str, s._str);
    }

    String &operator=(const String& s)
    {
        //不允许自己给自己赋值
        if (this != &s)
        {
        /*
        //方法1:
            delete[] _str;
            _str = new char[strlen(s._str) + 1];
            strcpy(_str, s._str);
        */
        //方法2:
            //先开空间,根据str的空间长度 
            char *pStr = new char[strlen(s._str) + 1];
            //将str的内容复制到新的字串中 
            strcpy(pStr, s._str);
            //将目标对象的字串删除 
            delete[] _str;
            //将复制的新字串指给目标对象
            _str = pStr;
        }
        return *this;
    }


我们可以看到,s1、s2、s3三个空间,三个不同地址

实现String类的深拷贝的现代写法

    //第一种写法,借助构造函数 
    String(const String& s)
        :_str(NULL)//必须要注意初始化为空
    {
        String tmpstr(s._str);
        swap(_str, tmpstr._str);
    }
    //第一种写法,借助构造函数 
    String &operator=(const String& s)
    {
        if (this != &s)
        {
            String tmpstr(s._str);
            swap(_str, tmpstr._str);
        }
        return *this;
    }

    //第二种写法:借助拷贝构造函数
    //必然会进行对象值拷贝操作(地址会变)
    String &operator = (String s)//s已经是形参的临时变量
    {
        swap(_str, s._str);
        return *this;
    }


自定义类型&内置类型

template<class T>

void Copy(T*dst, T*src, size_t size, bool IsPODType)
{
    if (IsPODType)
    {
        //优点:效率高 缺陷:浅拷贝
        memcpy(dst, src, size*sizeof(T));
    }
    else
    {
        //优点:不会出错 缺点:效率低
        for (size_t i = 0; i < size; i++)
        dst[i] = src[i];
    }
}

int main()
{
    int arr1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
    int arr2[10];
    Copy(arr2, arr1, sizeof(arr1) / sizeof(arr1[0]), true);

    //自定义类型,涉及深浅拷贝
    string str1[] = { "1111", "2222", "3333", "4444" };
    string str2[4];
    Copy(str2, str1, sizeof(str1) / sizeof(str1[0]), false);

    system("pause");
    return 0;
}

类模板特化应用—类型萃取

#include <string>
//对应自定义类型
struct FalseType
{
    static bool Get()
    {
        return false;
    }
};
//对应内置类型
struct TrueType
{
    static bool Get()
    {
        return true;
    }
};

template<class T>
struct TypeTraits
{
    typedef FalseType PODType;
};

template<>
struct TypeTraits<int>
{
    typedef TrueType PODType;
};

template<>
struct TypeTraits<char>
{
    typedef TrueType PODType;
};
template<class T>
void Copy(T*dst, T*src, size_t size)
{
    if (TypeTraits<T>::PODType::Get())
    {
        //优点:效率高 缺陷:浅拷贝
        memcpy(dst, src, size*sizeof(T));
    }
    else
    {
        //优点:不会出错 缺点:效率低
        for (size_t i = 0; i < size; i++)
            dst[i] = src[i];
    }
}

int main()
{
    int arr1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
    int arr2[10];
    Copy(arr2, arr1, sizeof(arr1) / sizeof(arr1[0]));

    //自定义类型,设计深浅拷贝
    string str1[] = { "1111", "2222", "3333", "4444" };
    string str2[4];
    Copy(str2, str1, sizeof(str1) / sizeof(str1[0]));

    system("pause");
    return 0;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值