C++学习之string的实现

张开发
2026/5/6 6:03:55 15 分钟阅读
C++学习之string的实现
前面我们已经学习了string的基本使用现在我们来学习string底层的实现。string的基础框架与私有成员定义首先定义类的私有成员与基础接口框架明确核心成员变量的含义为了防止与系统里的string冲突我们需要搞一个命名空间来包装namespace lx{ class string{ pulic: typedef char*iterator; iterator begin() { return _str; } iterator end() { return _str_size; } typedef const char*_const iterator; const_iterator begin() const { return _str; } const_iterator end() const { return _str _size; } private: char*_str; size_t _size; size_t _capacity; static const size_t npos; }; static const size_t npos; }一、默认成员函数1.构造函数构造函数为全缺省参数由于空字符串中默认有\0,全缺省参数为空字符串。string(const char*str) { _sizestrlen(_str); _capacity_size; _strnew char [_capacity1];//多开一个用来存放\0 strcpy(_str,str); }2.拷贝构造函数1.传统写法先根据拷贝的对象的容量开空间再进行拷贝string(const strings) :_size(s._size) ,_capacity(s._capacity) { _str(new char[_capacity1]); strcpy(_str,s._str); }2.现代写法构造一个新的对象再将新对象与拷贝对象的数据交换。string(const strings) :_str(nullptr) ,_size(0) ,capacity(0) { string tmp(s._str); swap(tmp); }3.赋值运算符重载函数通过深拷贝同样有传统写法与现代写法两种写法传统写法就是先开一块新空间拷贝数据再再释放掉原空间。string operatar(const strings) { if(*this!s) { char*tmp char new [s.capacity1]; strcpy(tmp,s._str); delete[]_str; _strtmp; _sizes._size; _capacitys.capacity; } return *this; }2.现代写法简单来说就是传值传参stringoperator(strings) { if(*this!s) { string tmp(s); swap(tmp); } return *this; }4.析构函数string~() { delete[]_str; _strnullptr; _size0; _capacity0; }二、迭代器模拟实现1.正向迭代器//正向迭代器 string::iterator string::begin() { return _str; } string::iterator string::end() { return _str _size; }2.const正向迭代器//正向迭代器 string::const_iterator string::begin()const { return _str; } string::const_iterator string::end()const { return _str _size; }三、容量大小相关函数1.size,capacitysize_t size()const { return _size; } size_t _capacity()const { return _capacity; }2.reserve和resizereserve:如果n比capacity大将capacity扩容到n或大于nvoid reserve(size_t n) { if(n_capacity) { char*tmpnew char[n1]; strcpy(tmp,_str); delete[]_str; _strtmp; _capacityn; } }resize:如果n比_size大根据n去扩容扩大的字符为ch,ch默认为\0void resize(size_t n,char ch\0) { if(n_size) { _sizen; _str[_size]\0; } else { if(n_capacity) { reserve(n); } for(size_t i_size;in;i) { _str[i]ch; } _sizen; _str[_size]\0; }3.clear和emptyvoid clear() { _str[0]\0; _size0; } void empty() { return _capacity0; }四、字符串的增删操作1.push_backpush_back的功能就是尾插一个字符尾插之前先判断空间是否足够不够先进行扩容再进行尾插操作且记得要在字符的末尾加上\0。void push_back(char ch) { if(_size_capacity) { reserve(_capacity0?4:2*_capacity); } _str[_size]ch; _str[_size1]\0; _size; }2.appendappend的功能是在字符串末尾尾插一个字符串先判断字符串的空间能否容纳尾插后的字符串若不能先增容。void append(const char*str) { size_t len_str strlen(_str); if(len_capacity) { reserve(len); } strcpy(_str_size,str); _sizelen; }3.operator重载可以实现字符与字符串之间直接使用运算符进行尾插stringoperaor(char ch)//重载字符 { push_back(ch); return*this; } stringoperator(char*str)//重载字符串 { append(str); return*this; }4.insertinsert的功能是在字符串的任意位置插入字符或字符串。void insert(size_t pos,char ch)//在pos位置插入字符 { assert(pos_size);//检查下标合法性 if(_size_capacity) { reserve(_capacity0?4:_capacity*2); } size_t end_size1; while(endpos) { _str[end1]_str[end]; --end; } _str[pos]ch; _size; return *this; } void insert(size_t pos,char*str)//在pos位置插入字符串 { assert(pos_size); size_t lenstrlen(_str); if(_sizelen_capacity) reserve(_sizelen); char*end_sizelen; while(endpos_size) { *(end1)*(end); end--; } strncpy(_strpos,str,len); _sizelen; return*this; }5.erase//删除指定位置的字符 stringerase(size_t pos,size_t lennpos) { assert(pos_size); size_t n_size-pos; if(lenn) //pos及之后的字符全删完 { _sizepos; _str[_size]\0; } else { strcpy(_strpos,_strposlen); _size-len; } return *this; }五、字符串操作1.c_str功能获取c形式的字符串charoperator[](size_t i) { assert(i_size); return _str[i]; }2.findfind函数功能为寻找指定字符并返回其下标size_t find(char ch,size_t pos0) { assert(pos_size); //检测下标合法性 for(size_t ipos;i_size;i)//从pos位置向后寻找字符 { if(_str[i]ch) { return i; //找到了返回其下标 } } else return npos; //没找到返回npos }六、关系运算符重载函数1.常用的六个关系运算符、!、、、、我们只需实现 和 两个关系运算符其余运算符可通过已有的组合关系来实现bool operator(const strings)const { return strcmp(_str,s._str)0; }bool operator(const strings)const { return strcmp(_str,s._str)0; }!bool operator!(const strings)const { return!(*thiss); }bool operator(const string s)const { return (*this s) || (*this s); }bool operator(const string s)const { return !(*this s); }bool operator(const string s)const { return !(*this s); }七、流插入与流提取流插入注意读取前会清掉原空间的数据且遇到空格或换行才会结束读取iostreamoperator(istreamin,strings) { s.clear(); char chin.get(); cinch; while(ch!ch!\n) { sch; chin.get(); } return in; }流提取ostreamoperator(ostreamout,strings) { for(size_t i0;is._size;i) { outs[i]; } return out; }getlinegetline的作用为读取一行含有空格的字符串遇到换行符时停止读取istream getline(istream in, string s) { s.clear(); char ch in.get(); while (ch ! \n) { s ch; ch in.get(); } return in; }

更多文章