前言:
学习了string的使用,总感觉了解不是很深厚;自己模拟实现string类来帮助自己理解。
这里只是实现了一部分内容(并没有实现完整的string类)。
先来实现string类里面的成员变量:
#include<iostream> namespace HL { class string { public: private: char* _str; size_t _size; size_t _capacity; const static size_t npos; }; const size_t HL::string::npos = -1; }
一、string默认成员函数(构造、析构、赋值运算符重载)
1.1、构造函数
1> 默认构造
默认构造函数就是不需要传参的构造函数;这里实现就开辟一个字符的空间存放 '\0'即可(_capacity不包括 '\0' )。
string() { _str = new char[1]; _str[0] = '\0'; _size = 0; _capacity = 0; }
2> 拷贝构造
拷贝构造,在实现时需要注意:是深拷贝,而不是浅拷贝(值拷贝)。
深拷贝(深拷贝简单来说就是,要开辟一块新的空间,把原空间里的值拷贝到新的空间里)。
string(const string& str) { _str = new char[str._capacity + 1]; memcpy(_str, str._str, str._size + 1); _size = str._size; _capacity = str._capacity; }
3> 其他构造
其他构造函数就有很多了,这里就实现以下这几个:
string (const char* s);
string(const char* s) { size_t len = strlen(s); _str = new char[len + 1]; memcpy(_str, s, len + 1); _size = len; _capacity = len; }
string (const char* s, size_t n);
string(const char* s, size_t n) { size_t len = strlen(s); if (n > len) { n = len; } _str = new char[n + 1]; memcpy(_str, s, n); _str[n] = '\0'; _size = n; _capacity = n; }
string (size_t n, char c);
string(size_t n, char c) { _str = new char[n + 1]; for (size_t i = 0; i < n; i++) { _str[i] = c; } _str[n] = '\0'; _size = n; _capacity = n; }
1.2、析构函数
析构函数比较简单,释放开辟的资源即可;
~string() { delete[] _str; _str = nullptr; _size = _capacity = 0; }
1.3、赋值运算符重载
赋值运算符有3个重载,这里就一一实现:
string& operator= (const string& str );
实现这个有很多种方法,
可以释放原空间,再开辟新的空间,将数据拷贝到新的空间中去
string& operator=(const string& str) { delete[] _str; _str = new char[str._capacity]; memcpy(_str, str._str, str._size + 1); _size = str._size; _capacity = str._capacity; return *this; }
可以调用拷贝构造,构造一个tmp、再将tmp与*this 中的值进行交换(要实现交换函数)
template <typename T> void Swap(T& x, T& y) { T tmp = x; x = y; y = tmp; } string& operator= (const string& str) { string tmp(str); Swap(_str, tmp._str); Swap(_size, tmp._size); Swap(_capacity, tmp._capacity); return *this; }
这里如果已经实现string类swap成员函数,就可以直接调用。
string& operator= (const char* s );
/*string& operator= (const char* s) { size_t len = strlen(s); delete[] _str; _str = new char[len + 1]; memcpy(_str, s, len + 1); _size = _capacity = len; return *this; }*/ string& operator= (const char* s) { string tmp(s); Swap(_str, tmp._str); Swap(_size, tmp._size); Swap(_capacity, tmp._capacity); return *this; }
string& operator= (char c );
string& operator= (char c) { delete[] _str; _str = new char[2]; _str[0] = c; _str[1] = '\0'; _size = _capacity = 1; return *this; }
二、元素访问与迭代器
2.1、迭代器
迭代器,虽然在string类中使用的不是很多,但在后面的容器中有大用处。
(在string类中就可以简单的理解成指针)。
//迭代器 typedef char* iterator; typedef const char* const_iterator; iterator begin() { return _str; } iterator end() { return (_str + _size); } const_iterator begin() const { return _str; } const_iterator end() const { return (_str + _size); }
实现了迭代器之后,范围for这个语法糖就可以使用了(底层就是迭代器)。
2.2、下标访问元素
实现下标访问,就是 [ ]运算符重载。
//下标访问 [ ] char& operator[] (size_t pos) { assert(pos >= _size); return *(_str + pos); } const char& operator[] (size_t pos) const { assert(pos >= _size); return *(_str + _size); }
at函数和 [ ] 运算符重载原理一样,这里就不重复写了。
三、增删查改
在实现增之前,要先实现一个函数,就是调整空间大小的(扩容来用)。
//扩容 void reserve(size_t n) { if (n > _capacity) { char* s = new char[n + 1]; memcpy(s, _str, _size); delete[] _str; _str = s; _capacity = n; } }
增删这里就实现这些成员函数。
1、push_back 、append 、operator+=
append重载比较多,这里就实现其中的几个。
//扩容 void reserve(size_t n) { if (n > _capacity) { char* s = new char[n + 1]; memcpy(s, _str, _size); delete[] _str; _str = s; _capacity = n; } } //增 void push_back(char c) { if (_size >= _capacity) { reserve((_capacity == 0) ? 4 : 2 * _capacity); } _str[_size] = c; _size++; _str[_size] = '\0'; } void append(const string& str) { size_t n = _size + str._size; if (n > _capacity) { reserve(n); } for (int i = 0; i < str._size; i++) { _str[_size + i] = str._str[i]; } _size += str._size; _str[_size] = '\0'; } void append(const char* s) { size_t len = strlen(s); int n = _size + len; if (n > _capacity) { reserve(n); } for (int i = 0; i < len; i++) { _str[_size + i] = s[i]; } _size = n; _str[_size] = '\0'; } void append(size_t n, char c) { if (_size + n > _capacity) { reserve(_size + n); } for (int i = 0; i < n; i++) { _str[_size + i] = c; } _size += n; _str[_size] = '\0'; } string& operator+=(const string& str) { this->append(str); return *this; } string& operator+=(const char* s) { this->append(s); return *this; } string& operator+=(char c) { this->push_back(c); return *this; }
【C++】—— string模拟实现(二)https://developer.aliyun.com/article/1621433