C++STL string

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;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值