C++模拟实现string(现代简易写时拷贝写法)

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

什么是写时拷贝

我们在只前的博客中讲述了深拷贝的写法string的深拷贝现代写法,我们window下vs就采用的就是深拷贝,而linux平台下则是采用写时拷贝的写法。写时拷贝顾名思义,就是写的时候再进行拷贝。也就是说,当我们拷贝构造或者赋值的时候,实际上只进行的浅拷贝,两个指针指向的是同一块new的空间而且拿了一块空间来做计数,记录着已经有多少指针同时指向这块空间了。当我们需要修改这个空间内容的时候,为了避免其他的对象对于的值也发生改变,则这时才给这个需要写的对象new一个新的空间,经常写操作。

写时计数

我们有很多类中记录有多少对象指向同一块空间,static 静态成员可以,但是这又一个问题,就是无论有几个new的空间,共用一个new计数,不错才怪。为了让这个计数器一直只跟着对应的一个new空间,我们采取开辟空间的时候多开辟4个,用来计数,实际的strcpy操作,是成员变量自加了一个int整形类型大小后才进行的。
具体实现代码:

#pragma once
// 1.现代写法写时拷贝
#include<iostream>
#include<string>
using namespace std;
#pragma warning (disable:4996)
class String
{
public:
    String(const char* str = "")
        :_str(new char[strlen(str)+1+4]), 
        _size(strlen(str)),
        _capacity (_size)
    {
        int *pstr = (int *)_str;
        *pstr = 1;
        _str = _str + 4;
        strcpy(_str, str);
    }
        // s1.Swap(s2); 
    void Swap(String& s)
    {
        swap(this->_str, s._str);
        swap(_size, s._size);
        swap(_capacity, s._capacity);
    }
        // String s2(s1) 
    String(const String& s)
        :_str(s._str),
        _size(strlen(s._str)),
        _capacity(strlen(s._str))
    {
        int *pstr = (int *)(_str - 4);
        *pstr += 1;
    }
    // s1 = s2 
    String& operator=(String s)
    {
        if (this->_str != s._str)
        {
            swap(_str, s._str);
            _size = s._size;
            _capacity = s._capacity;
        }
        return *this;
    }
    ~String()
    {
        _str = _str - 4;
        int* pstr = (int *)_str;
        if (--(*pstr) == 0)
        {
            delete[]_str;
            _str = NULL;
            _size = 0;
            _capacity = 0;
        }
    }
    const char* c_str()
    {
        return _str;
    }
    void Expand(size_t n)
    {
        _capacity += n;
        char * tmp = new char[_capacity+1+4];
        int * ptmp = (int *)tmp;
        *ptmp = (int)(*(_str - 4));
        tmp = tmp + 4;
        strcpy(tmp, _str);
        swap(tmp, _str);
    }
    void PushBack(char ch)
    {
        int *pstr = (int *)(_str - 4);
        if (*pstr > 1)
        {
            String tmp(_str);
            swap(_str, tmp._str);
        }
        if (_size >= _capacity)
        {
            Expand(10);
        }
        _str[_size++] = ch;
        _str[_size] = '\0';
    }
    void PushBack(const char* str)
    {
        int *pstr = (int *)(_str - 4);
        if (*pstr > 1)
        {
            String tmp(_str);
            swap(_str, tmp._str);
        }
        if (_size + strlen(str) >= _capacity)
        {
            Expand(strlen(str));
        }
        strcpy((_str + _size), str);
        _size += strlen(str);

    }
    void PopBack()
    {
        int *pstr = (int *)(_str - 4);
        if (*pstr > 1)
        {
            String tmp(_str);
            swap(_str, tmp._str);
        }
        _size--;
        _str[_size] = '\0';
    }
    void Insert(size_t pos, char ch)
 {
        int *pstr = (int *)(_str - 4);
        if (*pstr > 1)
        {
            String tmp(_str);
            swap(_str, tmp._str);
        }
        if (_size + 1 >= _capacity)
        {
            Expand(10);
        }
        assert(pos >= 0 && pos <= _size);
        memmove(_str + pos+1, _str + pos,_size - pos+1);
        _str[pos] = ch;
        _size++;
    }
    void Insert(size_t pos, const char* str)
    {
        int *pstr = (int *)(_str - 4);
        if (*pstr > 1)
        {
            String tmp(_str);
            swap(_str, tmp._str);
        }
        if (_size + strlen(str) >= _capacity)
        {
            Expand(strlen(str));
        }
        assert(pos >= 0 && pos <= _size);
        memmove(_str + pos + strlen(str), _str + pos,_size - pos+1);
        strncpy(_str + pos, str, strlen(str));
        _size += strlen(str);
    }
    void Erase(size_t pos, size_t n = 1)
    {
        int *pstr = (int *)(_str - 4);
        if (*pstr > 1)
        {
            String tmp(_str);
            swap(_str, tmp._str);
        }
        assert(pos >= 0 && pos < _size);
        strcpy(_str + pos, _str + pos + 1);
        _size -= 1;
    }
    size_t Find(char ch)
    {
        for (int i = 0; i <(int) _size; i++)
        {
            if (_str[i] == ch)
                return i;
        }
        return -1;
    }
    size_t Find(const char* str)
    {
        return Find(strstr(_str, str));

    }// ? 

                                  // s1 + 'a' 
    String operator+(char ch)
    {
        String tmp(_str);
        tmp.PushBack(ch);
        return tmp;
    }
    String& operator+=(char ch)
    {
        PushBack(ch);
        return *this;
    }
    String operator+(const char* str)
    {
        String tmp(_str);
        tmp.PushBack(str);
        return tmp;
    }
    String& operator+=(const char* str)
    {
        PushBack(str);
        return *this;
    }

    bool operator>(const String& s)
    {
        if (strcmp(_str, s._str) > 0)
            return true;
        else return false;
    }
    bool operator>=(const String& s)
    {
        return !(*this < s);
    }
    bool operator<(const String& s)
    {
        if (strcmp(_str, s._str) < 0)
            return true;
        else return false;
    }
    bool operator<=(const String& s)
    {
        return !(*this > s);
    }
    bool operator==(const String& s)
    {
        if (strcmp(_str, s._str) == 0)
            return true;
        else return false;
    }
    bool operator!=(const String& s)
    {
        return !(*this == s);
    }
    friend ostream& operator<<(ostream& cout, const String&s);
private:
    char* _str;
    size_t _size;
    size_t _capacity;
};
ostream & operator<<(ostream &cout, const String&s)
{
    cout << s._str;
    return cout;
}

猜你喜欢

转载自blog.csdn.net/weixin_40921797/article/details/82634158