更新string,这段时间学习了stl,发现共性的东西很多,string,vector,list等,弄懂他们的逻辑框架很重要,其实也是stl的规范,文章更新内容不管这些函数怎么用,就从大逻辑来讲
首先其实还是要搞清楚STL到底是什么东西
这里我们主要研究对象就是容器和算法,他们之间通过迭代器来“融合”,空间配置器就是内存池技术,这里的配置器呢,又称为适配器,适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总 结),该种模式是将一个类的接口转换成客户希望的另外一个接口。虽然stack和queue中也可以存放元素,但在STL中并没有将其划分在容器的行列,而是将其称为容器适配 器,这是因为stack和队列只是对其他容器的接口进行了包装,STL中stack和queue默认使用deque,而仿函数又称为函数对象是一个能行使函数功能的类。仿函数的语法几乎和我们普通的函数调用一样,不过作为仿函数的类,都必须重载 operator() 运算符。因为调用仿函数,实际上就是通过类对象调用重载后的 operator() 运算符。这个其实可以单独开一篇,先不细说,这里主要就是容器和算法还有迭代器,他们三者其实构成了stl最基本的框架
首先要定义string内成员,这里需要注意的是会牵扯到初始化列表顺序的问题,private里面成员的顺序必须和初始化列表相同
size_t _capacity;
size_t _size;
char* _str;
所以这里的构造函数不要使用初始化列表的方式,就采用最普通的构造函数,这里实现的功能就是s2("hello")
string(const char* str = "")
{
_size = strlen(str);
_capacity = _size;
_str = new char[_capacity + 1];
strcpy(_str, str);
}
接下来是不是改写拷贝构造函数了,这里我们采用现代写法,思想就是交换!
这里用到的知识点就是this指针和倒数第二句代码调用了上面写的构造函数
// s2(s1)
void swap(string& tmp)
{
::swap(_str, tmp._str);
::swap(_size, tmp._size);
::swap(_capacity, tmp._capacity);
}
string(const string& s)
:_str(nullptr)
, _size(0)
, _capacity(0)
{
string tmp(s._str);
swap(tmp); //this->swap(tmp);
}
之后就是赋值运算符重载
这里还是现代写法,也是要深刻理解this指针的作用
// s1 = s3
// s顶替tmp做打工人
string& operator=(string s)
{
swap(s);
return *this;
}
最后就是析构函数
~string()
{
delete[] _str;
_str = nullptr;
_size = _capacity = 0;
}
至此,一个最基本最基本的string类就写好了,之后我们需要的就是能够访问,修改,删除string内的元素,实现这些功能的基本是什么?
迭代器!
string迭代器就用两个指针来封装(就是原生指针):这里还分为普通迭代器和const迭代器,用来适配不同的遍历方式
iterator begin()
{
return _str;
}
iterator end()
{
return _str + _size;
}
const_iterator begin() const
{
return _str;
}
const_iterator end() const
{
return _str + _size;
}
有了迭代器遍历,还有一个经典的for+[]遍历,我们需要重载[]
const char& operator[](size_t pos) const
{
assert(pos < _size);
return _str[pos];
}
char& operator[](size_t pos)
{
assert(pos < _size);
return _str[pos];
}
接下来就是功能函数了
这里主要有查询大小和容量:size和capacity、修改大小和容量:reserve和resize,获取字符串内容:c_str,在pos位置插入,尾插,追加:insert、push_back和append,删除和清除:erase和clear,获取相同子字符串位置:substr,寻找:find等函数,最后还有一些运算符的重载:> , == , >= , <= , < , !=等
这些函数中比较重要的就是reserve和resize的区别,insert的实现(push_back和append的实现都可以复用insert),erase和find中出现的npos含义等