菜鸟笔记
提升您的技术认知

c++ sring类 浅拷贝&深拷贝&Copy On Write

c++ String类的三种实现

浅拷贝

class String
{
public:
    String(const char* pdata)//构造函数
        :_pdata(new char[strlen(pdata) + 1])
    {
        strcpy(_pdata, pdata);
    }
    String(const String&s)//拷贝构造
        :_pdata(s._pdata)
    {}
    ~String()//析构函数
    {
        if (NULL != _pdata)
        {
            delete[]_pdata;
            _pdata = NULL;
        }
    }
    String &operator=(const String&s)
    {
        //检查自赋值
        if (this != &s)
        {
            char*temp = new char[strlen(s._pdata) + 1];
            strcpy(temp, s._pdata);
            delete[]_pdata;
            _pdata = temp;
        }
        return *this;
    }
private:
    char*_pdata;
};
void main()
{
    String s1 ("hello world");
    String s2=s1;
}

浅拷贝

当类里面有指针对象时,进行简单赋值的浅拷贝,两个对象指向同一块内存,存在崩溃的问题!这里我们要进行深拷贝。

深拷贝

# define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
using namespace std;
class String
{
public:
    String(const char* pdata)//构造函数
        :_pdata(new char[strlen(pdata) + 1])
    {
        strcpy(_pdata, pdata);
    }
    String(const String&s)//拷贝构造
        :_pdata(new char[strlen(s._pdata) + 1])
    {
        strcpy(_pdata, s._pdata);
    }
    ~String()//析构函数
    {
        if (NULL != _pdata)
        {
            delete[]_pdata;
            _pdata = NULL;
        }
    }
    String &operator=(const String&s)
    {
        //检查自赋值
        if (this != &s)
        {
            char*temp = new char[strlen(s._pdata) + 1];
            strcpy(temp, s._pdata);
            delete[]_pdata;
            _pdata = temp;
        }
        return *this;
    }
private:
    char*_pdata;
};
//简洁版
class String
{
public:
    String(const char* pData)
        : _pData(new char[strlen(pData) + 1])
    {
        strcpy(_pData, pData);
    }

    String(const String& s)
        : _pData(NULL)
    {
        String temp(s._pData);
        std::swap(_pData, temp._pData);
    }

     String& operator=(const String& s)
         {
             if (this != &s)
             {
                 String temp(s._pData);
                 std::swap(_pData, temp._pData);
             }
             return *this;
         }
     ~String()
     {
         if (NULL != _pData)
         {
             delete[] _pData;
             _pData = NULL;
         }
     }
private:
    char* _pData;
};
void main()
{
    String s1 ("hello world");
    String s2=s1;
}

深拷贝

写时拷贝

#include<iostream>
#include<string.h>
#include<assert.h>
namespace COW
{
    class String
    {
    public:
        String(const char* pData)
            : _pData(new char[strlen(pData) + 1])
            , _refCount(new int)
        {
            *_refCount = 1;
            strcpy(_pData, pData);
        }

        // String s2(s1);
        String(String& s)
            : _pData(s._pData)
            , _refCount(s._refCount)
        {
            ++(*_refCount);
        }

        // s1 = s2;
        String& operator=(String s)
        {
            if (this != &s)
            {
                if (--(*_refCount) == 0)
                {
                    delete[] _pData;
                    delete _refCount;
                }

                _pData = s._pData;
                _refCount = s._refCount;
                ++(*_refCount);
            }

            return *this;
        }

        ~String()
        {
            if (--(*_refCount) == 0)
            {
                delete[] _pData;
                delete _refCount;
            }
        }
        // 返回值  函数名(参数)
        char& operator[](int index)
        {
            // 检测返回
            // *_refCount > 1
            // *_refCount = 1
            if (*_refCount > 1)
            {
                (*_refCount)--;
                String temp(_pData);
                _pData = temp._pData;
                _refCount = temp._refCount;
                (*_refCount)++;
            }
            return _pData[index];
        }
        /*const char& operator[](int index)const
        {

            return _pData[index];
        }*/
    private:
        char* _pData;
        int* _refCount;
    };
}
void FunTest()
{
    COW::String s1("12345");
    COW::String s2("123456789");
    const COW::String s3 = s2;
    s1 = s2;
    s2[0] = '6';
    //std::cout << s3[1];
}
int main()
{
    FunTest();
    return 0;
}

string 之间拷贝时不是深拷贝,只拷贝了指针, 也就是共享同一个字符串内容, 只有在内容被修改的时候, 才真正分配了新的内存并 copy 。 比如 s[0]='1' 之类的修改字符串内容的一些write操作, 就会申请新的内容,和之前的共享内存独立开。 所以称之为 『copy-on-write』