在上节的学习,简单学习了string的用法,但只有了解底层原理并复现string部分代码才可以更好的理解和应用,我实现了string的部分功能。
string简单用法 复习
为了不与string.h文件重复(iostream中有时会包含,C++和Linux细节上有差别,暂时忽略),必须定义自己的命名空间,我的定义zgz(张公子)
namespace zgz {}
在内部开始书写
要书写一个较为完整的string,首先分析string的构成:字符串、长度、空间大小
因此,对string的基本构造如下:
class string { public: string(const char* str = "") { _size = strlen(str); _capacity = _size; _str = new char[_capacity + 1];// +1 是 \0 strcpy(_str, str); } //对应的析构函数应该完成析构操作,并释放空间 ~string() { delete[] _str; _str = nullptr;//也可以没有这行 _size = _capacity = 0; } private: char* _str; size_t _size; size_t _capacity;
有了字符串,我们首先要完成的功能就是遍历并输出。
在Test.cpp中:
下面用到2种遍历,
int main() { //1.for zgz::string s("abc1234"); for (size_t i = 0; i < s.size(); ++i) { cout << s[i] << " "; } cout << endl; //2.迭代器 zgz::string::iterator it = s.begin(); //auto it = s.begin(); while (it != s.end()) { cout << *it << " "; ++it; } }
其中,原生指针就是天然的迭代器
输出结果为:
迭代器写法如下:
//迭代器 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; }
此时,我们想到string的常用功能:
测试代码如下:
有明显的报错,这是因为没有重载这个功能。
实现如下:
char& operator[](size_t i) { assert(i < _size);//不能越界 return _str[i]; } size_t size() { return _size; }
此时:
用来改变空间大小的:
void reserve(size_t n) { if (n > _capacity) { char* tmp = new char[n]; strcpy(tmp, _str); delete[] _str; _str = tmp; _capacity = n; } }
当空间大小可以改变以后,就可以实现插入等操作了
void push_back(char ch) { if (_size == _capacity) { reserve(2 * _capacity); } _str[_size] = ch; ++_size; }
void append(const char* str) { size_t len = strlen(str); if (_size + len > _capacity) { reserve(_size + len); } strcpy(_str + _size, str); _size += len; }
有两种方式,分别是:s2(s1)和s3 = s1,整理思路,简单的拷贝构造有什么构造什么。
例如——string,需要构造str、capacity、size,但如果比较复杂,构造起来费时费力,那么采取新方法,让别人构造好,然后swap即可,具体实现如下:
//s1.swap(s2) void swap(string& s) { std::swap(_str, s._str); std::swap(_size, s._size); std::swap(_capacity, s._capacity); } //s2(s1) string(const string& s) :_str(nullptr) , _capacity(0) , _size(0) { string tmp(s._str); swap(tmp); } //s3 = s1 string& operator=(string s) { swap(s); return *this; }
其中的swap单纯为后面服务
测试代码:
zgz::string s2(s); for (size_t i = 0; i < s2.size(); i++) { cout << s2[i] ; } cout << endl; zgz::string s3 = s; for (size_t i = 0; i < s3.size(); i++) { cout << s3[i] ; } cout << endl;
结果如下:
// s += 'x'; string& operator+=(char ch) { push_back(ch); return *this; } string& operator+=(const char* str) { append(str); return *this; } string& operator+=(const string& s) { append(s._str); return *this; }