c++ string模拟实现

一.constructor构造函数

string的7种构造方法:

1.构造函数的使用

2.构造函数的模拟实现

使用字符串构造和无参构造的实现(注意要给'\0'多开一个字节的空间)

    构造函数
    string::string(const char* str )//考虑无参构造
            :_str(nullptr) //构造列表,没有参数时_str=nullptr

    {

        _size = strlen(str);
        _capacity = _size;  
        _str = new char[_capacity+1]; // 给'\0'多开一个字节空间

        strcpy(_str, str);//把str的内容拷贝到_str中
    }

拷贝构造的实现

     拷贝构造(深拷贝)
    string::string(const string& s)
    {    
        _capacity = s._capacity;
        _size = s._size;
        _str = new char[s._capacity];//开空间+拷贝
        strcpy(_str, s._str);
    }

其实拷贝构造也可以这样写:

    string::string(const string& s)
    {
        //本来是_str自己开空间,让tmp给_str打工
        string tmp(s._str);
        swap(tmp);//交换tmp和*this的成员变量
    }

    void string::swap(string& s)
    {
        std::swap(_str, s._str);
        std::swap(_size, s._size);
        std::swap(_capacity, s._capacity);

    }

二.析构函数

构造函数是对象创建的时候自动调用的,而析构函数就是对象在销毁的时候自动调用的

    //析构函数
    string::~string()
    {
        
delete[] _str;
        _str =
nullptr;
        _size = 0;
        _capacity = 0;
    }

三.扩容

1.resrver

如果开的空间比n小,不做操作;如果开的空间比n大,开n+1空间并拷贝_str的内容到tmp中,再把原空间释放让_str指向tmp,_capcaity=n+1

    void string::reserve(size_t n)
    {
        //判断一下n和capacity的大小
        if (n > _capacity)
        {
            char* tmp = new char[n+1];
            strcpy(tmp, _str);
            delete[] _str; //把原空间释放
            _str = tmp;
            _capacity = n+1;
        }
    }

 四.插入删除操作

1.push_back

尾插一个字符

尾插之前要检查是否capacity==size进行扩容,直接让最后的元素_str[_size] = ch++size, _str[_size] = '\0'(尾插会把最后的'\0'覆盖,所以要将最后一位变成'\0'

    void string::push_back(char ch)
    {
        if (_size == _capacity)
        {
            int newcapacity = _capacity==0?4: _capacity * 2;
            //防止_str中什么都没有
            //上面不需要修改_capacity

            reserve(newcapacity);
        }
        _str[_size] = ch;
        ++ _size;
        _str[_size] = '\0';
    }

 2.append

尾插一个字符串

计算一下要插入的字符串长度,如果_size(原长度) + len(str长度) + 1('\0') > _capacity就需要扩容, strcpy(_str + _size, str)将str内容拷贝过去,size+=len(strcat在_str追加str内容时不会在末尾加'\0')


    void string::append(const char* str)
    {
        size_t len = strlen(str);
        if (_size + len + 1 > _capacity)
        {
            reserve(_size + len + 1);
        }

        strcpy(_str + _size, str);//strcpy会自动把'\0'拷贝过来
        _size += len;
    }
    

 3.operator+=

运算符重载

重载两个版本一个可以插入字符,一个可以插入字符串

    //重载两个版本
    string& string::operator+= (const char ch)
    {
        (*this).push_back(ch);

        return *this;
    }
    
    string& string::operator+= (const char* str)
    {    
        (*this).append(str);

        return *this;
    }

4.insert 

在pos插入一个字符push_back类似,不过要在插入前把pos后面的数据都向后移动一个

 在pos插入一个字符串和append类似,不过要在插入前把pos后面的数据都向后移动len长度

 //重载两个版本

void string::insert(size_t pos, char ch)
    {
        assert(pos <= _size);

        if (_size == _capacity)
        {
            int newcapacity = _capacity == 0 ? 4 : _capacity * 2;
            //防止_size中什么都没有
            //上面不需要修改_capacity

            reserve(newcapacity);
        }

        size_t cur = _size+1;//如果pos=0,cur-->size_t,需要将'\0'一起移动
        while (pos < cur)
        {
            _str[cur] = _str[cur-1];
            --cur;
        }
        
        _str[pos] = ch;
        ++_size;
    }

    void string::insert(size_t pos,const char* str)
    {
        assert(pos <= _size);

        size_t len = strlen(str);
        if (_size + len + 1 > _capacity)
        {
            reserve(_size + len + 1);
        }

        size_t cur = _size + 1;//如果pos=0,cur-->size_t,需要将'\0'一起移动
        while (pos < cur)
        {
            _str[cur+len-1] = _str[cur - 1];
            --cur;
        }

        strncpy(_str + pos, str, len);
        _size += len;
    }

5.erase

删除pos位置后面len个数据 

void string::erase(size_t pos, size_t len)
    {
        assert(pos < _size);

        if (len==npos || pos + len >= _size)
        {
            _size = pos - 1;
            _str[pos] = '\0';
        }
        else
        {
            strcpy(_str + pos, _str + pos + len);
            _size -= len;
        }
    }

  • 43
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值