String
typedef basic_string<char> string;
typedef basic_string<wchar_t> wstring;
String类是由模板类base_string<classs CharT , class traits, class alloc>实例化生成的一个类,base_string是由string_base继承而来的子类
String_base类源码
template <class _Tp, class _Alloc> class _String_base {
public:
typedef _Alloc allocator_type;
allocator_type get_allocator() const { return allocator_type(); }
protected:
typedef simple_alloc<_Tp, _Alloc> _Alloc_type;
//和vector类似在base类中定义,start指向内存区开始位置,finish指向已经使用的内存的末尾,end_of_storage指向动态内存区的末尾
_Tp* _M_start;
_Tp* _M_finish;
_Tp* _M_end_of_storage;
// Precondition: 0 < __n <= max_size().
//申请内存
_Tp* _M_allocate(size_t __n) { return _Alloc_type::allocate(__n); }
//释放内存
void _M_deallocate(_Tp* __p, size_t __n) {
if (__p)
_Alloc_type::deallocate(__p, __n);
}
void _M_allocate_block(size_t __n) {
if (__n <= max_size()) {
_M_start = _M_allocate(__n);
_M_finish = _M_start;
_M_end_of_storage = _M_start + __n;
}
else
_M_throw_length_error();
}
void _M_deallocate_block()
{ _M_deallocate(_M_start, _M_end_of_storage - _M_start); }
size_t max_size() const { return (size_t(-1) / sizeof(_Tp)) - 1; }
//默认构造
_String_base(const allocator_type&)
: _M_start(0), _M_finish(0), _M_end_of_storage(0) { }
//分配n个元素空间的构造函数
_String_base(const allocator_type&, size_t __n)
: _M_start(0), _M_finish(0), _M_end_of_storage(0)
{ _M_allocate_block(__n); }
~_String_base() { _M_deallocate_block(); }
};
Base_string类
template <class _CharT, class _Traits, class _Alloc>
class basic_string : private _String_base<_CharT,_Alloc> {
public:
typedef _CharT value_type;
typedef _Traits traits_type;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef const value_type* const_iterator;
typedef value_type* iterator;
static const size_type npos;
//定义String_base类
typedef _String_base<_CharT,_Alloc> _Base;
public: // Constructor, destructor, assignment.
typedef typename _Base::allocator_type allocator_type;
allocator_type get_allocator() const { return _Base::get_allocator(); }
//默认构造函数,不带任何参数的默认构造函数会申请一个含8个元素的内存块
explicit basic_string(const allocator_type& __a = allocator_type())
: _Base(__a, 8) { _M_terminate_string(); }
//指定字符串长度的构造函数,实际上会申请一个长度为n+1的元素的内存块
struct _Reserve_t {};
basic_string(_Reserve_t, size_t __n,
const allocator_type& __a = allocator_type())
: _Base(__a, __n + 1) { _M_terminate_string(); }
//复制构造函数
//类似于:string s1=”1234”;, string s2(s1);
//1.调用String_base的构造函数,将M_finish, M_Strat, M_end_of_storage全部置为0
//2.调用M_range_initialize进行赋值
//3.计算字符串长度n,申请一个n+1个元素的内存块,调用uninitialized_copy将s的内存拷贝到本实例的有效区域中,再将M_finish后面的内存写为0
basic_string(const basic_string& __s) : _Base(__s.get_allocator())
{ _M_range_initialize(__s.begin(), __s.end()); }
basic_string(const basic_string& __s, size_type __pos, size_type __n = npos,
const allocator_type& __a = allocator_type())
: _Base(__a) {
if (__pos > __s.size())
_M_throw_out_of_range();
else
_M_range_initialize(__s.begin() + __pos,
__s.begin() + __pos + min(__n, __s.size() - __pos));
}
//接收字符串的构造函数,类似于string s(“123”);这种情况下会调用
//计算字符串的长度,然后把字符串首地址和末地址传入M_range_initialize函数中
basic_string(const _CharT* __s, size_type __n,
const allocator_type& __a = allocator_type())
: _Base(__a)
{ _M_range_initialize(__s, __s + __n); }
basic_string(const _CharT* __s,
const allocator_type& __a = allocator_type())
: _Base(__a)
{ _M_range_initialize(__s, __s + _Traits::length(__s)); }
//生成多个相同字符的string的构造函数
//类似于string s(10, ‘a’);等效于string s(“aaaaaaaaaa”);
basic_string(size_type __n, _CharT __c,
const allocator_type& __a = allocator_type())
: _Base(__a, __n + 1)
{
_M_finish = uninitialized_fill_n(_M_start, __n, __c);
_M_terminate_string();
}
// Check to see if _InputIterator is an integer type. If so, then
// it can't be an iterator.
//构造函数
//类似于char* cstr = “123abc”;
//string str(cstr, cstr+3);实例化一个内容为”123”的string对象
basic_string(const _CharT* __f, const _CharT* __l,
const allocator_type& __a = allocator_type())
: _Base(__a)
{
_M_range_initialize(__f, __l);
}
~basic_string() { destroy(_M_start, _M_finish + 1); }
basic_string& operator=(const basic_string& __s) {
if (&__s != this)
assign(__s.begin(), __s.end());
return *this;
}
basic_string& operator=(const _CharT* __s)
{ return assign(__s, __s + _Traits::length(__s)); }
basic_string& operator=(_CharT __c)
{ return assign(static_cast<size_type>(1), __c); }
private: // Helper functions used by constructors
// and elsewhere.
void _M_construct_null(_CharT* __p) {
construct(__p);
}
static _CharT _M_null() {
# ifndef __STL_DEFAULT_CONSTRUCTOR_BUG
return _CharT();
# else
return (_CharT) 0;
# endif
}
private:
// Helper functions used by constructors. It is a severe error for
// any of them to be called anywhere except from within constructors.
void _M_terminate_string() {
__STL_TRY {
_M_construct_null(_M_finish);
}
__STL_UNWIND(destroy(_M_start, _M_finish));
}
void _M_range_initialize(const _CharT* __f, const _CharT* __l) {
ptrdiff_t __n = __l - __f;
_M_allocate_block(__n + 1);
_M_finish = uninitialized_copy(__f, __l, _M_start);
_M_terminate_string();
}
}
//迭代器
public: // Iterators.
//begin返回内存区域的头部迭代器
iterator begin() { return _M_start; }
//end返回尾部迭代器
iterator end() { return _M_finish; }
//常量迭代器
const_iterator begin() const { return _M_start; }
const_iterator end() const { return _M_finish; }
//返回反向迭代器
reverse_iterator rbegin()
{ return reverse_iterator(_M_finish); }
reverse_iterator rend()
{ return reverse_iterator(_M_start); }
const_reverse_iterator rbegin() const
{ return const_reverse_iterator(_M_finish); }
const_reverse_iterator rend() const
{ return const_reverse_iterator(_M_start); }
public: // Size, capacity, etc.
//返回目前已经使用了的内存单元数
size_type size() const { return _M_finish - _M_start; }
size_type length() const { return size(); }
size_t max_size() const { return _Base::max_size(); }
//调整string内存大小
void resize(size_type __n, _CharT __c) {
if (__n <= size())
erase(begin() + __n, end());
else
append(__n - size(), __c);
}
void resize(size_type __n) { resize(__n, _M_null()); }
void reserve(size_type = 0);
//当前申请的内存一共可以放下多少个元素
size_type capacity() const { return (_M_end_of_storage - _M_start) - 1; }
void clear() {
if (!empty()) {
_Traits::assign(*_M_start, _M_null());
destroy(_M_start+1, _M_finish+1);
_M_finish = _M_start;
}
}
bool empty() const { return _M_start == _M_finish; }
增加,删除,查询,修改相关函数
Reserve函数
改变capacity的返回值,所以它内部会导致动态内存的申请和释放
// Change the string's capacity so that it is large enough to hold
// at least __res_arg elements, plus the terminating null. Note that,
// if __res_arg < capacity(), this member function may actually decrease
// the string's capacity.
template <class _CharT, class _Traits, class _Alloc>
void basic_string<_CharT,_Traits,_Alloc>::reserve(size_type __res_arg) {
//如果res_arg超出系统最大支持量,出错
if (__res_arg > max_size())
_M_throw_length_error();
//n是新的大小,在参数res_arg和size中选择一个更大的再加一
size_type __n = max(__res_arg, size()) + 1;
//使用内存分配器M_allocate分配n个元素所需要的内存,将返回值给new_start,新的finish也为new_start
pointer __new_start = _M_allocate(__n);
pointer __new_finish = __new_start;
//尝试把M_start到M_finish的那一片内存拷贝到new_start开始的内存区域,同时把new_finish指向最后一个有效元素的后一个内存区域,如果发生异常,则释放刚刚申请的内存
__STL_TRY {
__new_finish = uninitialized_copy(_M_start, _M_finish, __new_start);
_M_construct_null(__new_finish);
}
__STL_UNWIND((destroy(__new_start, __new_finish),
_M_deallocate(__new_start, __n)));
//调用M_start到M_finish+1元素的析构函数,然后再调用M_deallocate_block释放原来占用的动态内存。最后把M_start和M_finish改成相应的新值
destroy(_M_start, _M_finish + 1);
_M_deallocate_block();
_M_start = __new_start;
_M_finish = __new_finish;
_M_end_of_storage = __new_start + __n;
}
Append函数
//函数在string后面添加n个字符C
template <class _CharT, class _Traits, class _Alloc>
basic_string<_CharT,_Traits,_Alloc>&
basic_string<_CharT,_Traits,_Alloc>::append(size_type __n, _CharT __c) {
//判断n和加上n后是否超出系统最大支持元素个数
if (__n > max_size() || size() > max_size() - __n)
_M_throw_length_error();
//判断当前大小加上n是否超出capacity大小,如果超出调用reserve函数,扩大空间
//传入的参数是size+max(size,n)克制最终传入到reserve的参数res_arg至少是size的两倍
if (size() + __n > capacity())
reserve(size() + max(size(), __n));
if (__n > 0) {
//把M_finish+1往后的n-1个元素用c调用无初始化填充函数进行填充
uninitialized_fill_n(_M_finish + 1, __n - 1, __c);
//把新的结尾M_finish+n指向的内存单元的内容设置为0
__STL_TRY {
_M_construct_null(_M_finish + __n);
}
__STL_UNWIND(destroy(_M_finish + 1, _M_finish + __n));
//M_finish指向的值设为c
_Traits::assign(*_M_finish, __c);
//设置新的末尾
_M_finish += __n;
}
return *this;
}
//append函数,支持从一个字符数组取数据,这个append的内存申请是自己实现的申请动态内存,没有调用reserve函数取扩充容量
template <class _Tp, class _Traits, class _Alloc>
basic_string<_Tp, _Traits, _Alloc>&
basic_string<_Tp, _Traits, _Alloc>::append(const _Tp* __first,
const _Tp* __last)
{
if (__first != __last) {
const size_type __old_size = size();
ptrdiff_t __n = __last - __first;
if (__n > max_size() || __old_size > max_size() - __n)
_M_throw_length_error();
if (__old_size + __n > capacity()) {
const size_type __len = __old_size + max(__old_size, (size_t) __n) + 1;
pointer __new_start = _M_allocate(__len);
pointer __new_finish = __new_start;
__STL_TRY {
__new_finish = uninitialized_copy(_M_start, _M_finish, __new_start);
__new_finish = uninitialized_copy(__first, __last, __new_finish);
_M_construct_null(__new_finish);
}
__STL_UNWIND((destroy(__new_start,__new_finish),
_M_deallocate(__new_start,__len)));
destroy(_M_start, _M_finish + 1);
_M_deallocate_block();
_M_start = __new_start;
_M_finish = __new_finish;
_M_end_of_storage = __new_start + __len;
}
else {
const _Tp* __f1 = __first;
++__f1;
uninitialized_copy(__f1, __last, _M_finish + 1);
__STL_TRY {
_M_construct_null(_M_finish + __n);
}
__STL_UNWIND(destroy(_M_finish + 1, _M_finish + __n));
_Traits::assign(*_M_finish, *__first);
_M_finish += __n;
}
}
return *this;
}
Assign函数,赋值函数
把目标字符串赋值为string,从头复制
内部逻辑是:
1.如果参数字符串较短,小于size则先拷贝,然后前l-f是有效元素,new_finish指向第l-f元素,再把new_finish到老M_finish的元素调用析构函数(调用析构函数,没有释放内存),最后把M_finish指向new_finish指向的元素
2.否则就先拷贝前size个元素,然后调用append
template <class _CharT, class _Traits, class _Alloc>
basic_string<_CharT,_Traits,_Alloc>&
basic_string<_CharT,_Traits,_Alloc>::assign(const _CharT* __f,
const _CharT* __l)
{
const ptrdiff_t __n = __l - __f;
if (static_cast<size_type>(__n) <= size()) {
_Traits::copy(_M_start, __f, __n);
erase(_M_start + __n, _M_finish);
}
else {
_Traits::copy(_M_start, __f, size());
append(__f + size(), __l);
}
return *this;
}
Insert函数
//在position位置插入n个字符c
template <class _CharT, class _Traits, class _Alloc>
void basic_string<_CharT,_Traits,_Alloc>
::insert(basic_string<_CharT,_Traits,_Alloc>::iterator __position,
size_t __n, _CharT __c)
{
if (__n != 0) {
//当空闲的区域数量大于n+1则进入下面的流程,为什么是n+1而不是大于n,因为字符串需要留下一个字节的内存来填充字符串结束符
if (size_type(_M_end_of_storage - _M_finish) >= __n + 1) {
//插入点到末尾一共多少个元素
const size_type __elems_after = _M_finish - __position;
iterator __old_finish = _M_finish;
//插入点到末尾可以容纳n个元素
if (__elems_after >= __n) {
uninitialized_copy((_M_finish - __n) + 1, _M_finish + 1,
_M_finish + 1);
_M_finish += __n;
_Traits::move(__position + __n,
__position, (__elems_after - __n) + 1);
_Traits::assign(__position, __n, __c);
}
else {
//这种情况下,待插入的元素肯定是分两部分插入到内存中,第一部分长度为elem_after,这部分插入到position到M_finish中,第二部分为n-elem_after个元素,放在M_finish之后。实现中,首先将n-elem_after个元素放在M_finish后面,此时M_finish就会修改为新的末尾。完了再把原来position到末尾的元素拷贝到新的末尾M_finish所在的内存区域上。最后将剩下的elem_after个c字符插入到position
uninitialized_fill_n(_M_finish + 1, __n - __elems_after - 1, __c);
_M_finish += __n - __elems_after;
__STL_TRY {
uninitialized_copy(__position, __old_finish + 1, _M_finish);
_M_finish += __elems_after;
}
__STL_UNWIND((destroy(__old_finish + 1, _M_finish),
_M_finish = __old_finish));
_Traits::assign(__position, __elems_after + 1, __c);
}
}
else {
//当内存不足时,分配至少原来两倍的空间,然后把原来M_start到position的拷贝过去,再把n个c字符拷贝过去,最后再把原来position到M_finish的拷贝过去,最后释放原来的内存,将M_start,M_finish,M_end_of_storage修改区维护新申请的内存
const size_type __old_size = size();
const size_type __len = __old_size + max(__old_size, __n) + 1;
iterator __new_start = _M_allocate(__len);
iterator __new_finish = __new_start;
__STL_TRY {
__new_finish = uninitialized_copy(_M_start, __position, __new_start);
__new_finish = uninitialized_fill_n(__new_finish, __n, __c);
__new_finish = uninitialized_copy(__position, _M_finish,
__new_finish);
_M_construct_null(__new_finish);
}
__STL_UNWIND((destroy(__new_start,__new_finish),
_M_deallocate(__new_start,__len)));
destroy(_M_start, _M_finish + 1);
_M_deallocate_block();
_M_start = __new_start;
_M_finish = __new_finish;
_M_end_of_storage = __new_start + __len;
}
}
}
Replace函数
将first到last区间替换为n个字符c
template <class _CharT, class _Traits, class _Alloc>
basic_string<_CharT,_Traits,_Alloc>&
basic_string<_CharT,_Traits,_Alloc>
::replace(iterator __first, iterator __last, size_type __n, _CharT __c)
{
const size_type __len = static_cast<size_type>(__last - __first);
//如果区间个数大于n
if (__len >= __n) {
_Traits::assign(__first, __n, __c);
erase(__first + __n, __last);
}
else {
_Traits::assign(__first, __len, __c);
insert(__last, __n - __len, __c);
}
return *this;
}