前言
因为学习了string的相关知识,了解了string大部分接口的底层实现原理,所以我决定自己模拟实现一个mini版的string类,用来加深对string各方面知识的理解。 如果有错误或不足之处,还望各位读者小伙伴们指出。
一、包含的相关头文件
代码语言:javascript复制#include<iostream>
#include<assert.h>
#include<cstring>
using std::ostream;
using std::istream;
using std:: cout;
using std:: endl;
二、构造和析构
1.构造函数
代码语言:javascript复制 //构造
string(const char* str = "")
{
size_t len = strlen(str);
_capacity = _size = len;
_str = new char[_capacity 1];
strcpy(_str, str);
}
2.拷贝构造
1.传统写法
该对象自己一点一点的进行深拷贝
代码语言:javascript复制 //拷贝构造
string(const string& s)
{
_str = new char[s._capacity 1];
_size = s._size;
_capacity = s._capacity;
strcpy(_str, s._str);
}
2.现代写法
找一个中间对象,让这个中间对象用参数的值进行直接构造,再将这个中间对象的内容与自己的内容进行交换。相较于传统写法,现代写法更加简洁。
代码语言:javascript复制 //拷贝构造
string(const string& s)
:_str(nullptr),//此处要注意将该对象的地址赋值为nullptr,否则析构中间对象时会因为发生野指针的访问而导致程序崩溃。
_size(0),
_capacity(0)
{
string temp(s);
swap(temp);
}
此处的swap用的是string自己实现的swap,为什么不用库里的swap呢?因为库里的swap是进行深拷贝,会降低效率。我们自己实现的swap只需要进行浅拷贝,即将它们对应的资源进行交换即可。
代码语言:javascript复制 void swap(string& s)
{
std::swap(_str, s._str);
std::swap(_size, s._size);
std::swap(_capacity, s._capacity);
}
3.赋值运算符重载
1.传统写法
代码语言:javascript复制 //赋值运算符重载
string& operator=(const string &s)
{
if (this != &s)
{
char* temp = new char[s._capacity 1];//用一个中间值记录新开辟的空间,如果开辟空间成功,再将该空间的地址给_str。避免因为开辟空间失败,_str原本的内容也销毁的情况发生。
strcpy(temp, s._str);
delete[] _str;
_str = temp;
_capacity = s._capacity;
_size = s._size;
}
return *this;
}
2.现代写法
与拷贝构造的现代写法思想类似,可以使程序更加简洁。并且此处不需要专门定义一个中间对象,因为传值传参传过来的形参是实参拷贝构造出来的对象,它就是一个很好的中间对象,我们直接和它进行交换即可。
代码语言:javascript复制 //赋值运算符重载
string& operator=(string s)
{
swap(s);
return *this;
}
4.析构函数
代码语言:javascript复制 //析构
~string()
{
delete[] _str;
_str = nullptr;//释放指针所指向的空间后要将该指针置为空(避免出现野指针的非法访问)
_size = _capacity = 0;
}
三、iterator
迭代器是一个使用起来像指针的东西,实际上string的迭代器就是char*类型的指针,因此我们先在最开始进行typedef
代码语言:javascript复制typedef char* iterator;
定义两个迭代器:分别指向字符串开头和结尾
代码语言:javascript复制 iterator begin()
{
return _str;
}
iterator end()
{
return _str _size;
}
四、modify
1.push_back(尾插一个字符)
string只提供了push_back的接口没有提供头插的接口,因为头插需要移动数据,效率很低,所以尽量不要在string中使用头插。
代码语言:javascript复制 void push_back(char c)
{
if (_size == _capacity)
{
size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;//要考虑到如果初始字符串的容量为0的情况
reserve(newcapacity);
_capacity = newcapacity;
}
_str[_size ] = c;
_str[_size] = '