STL源码剖析之vector

0.导语

vector的数据安排以及操作方式,与array非常相似。两者的唯一差别在于空间的运用的灵活性,array是静态的,一旦配置了就不能改变,而 vector是动态空间,随着元素的加入,它的内部机制会自行扩充空间以容纳新元素。下面一起来看一下vector的"内部机制",怎么来实现空间配置策略的。

1.vector

_Vector_base中开头有两行比较难理解,下面一个一个分析:

1.1 _Tp_alloc_type

开头处定义:

  1. typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template rebind<_Tp>::other _Tp_alloc_type;

gnu_cxx::alloc_traits中:对应文件为:ext/alloc_traits.h

  1. template<typename _Tp>
  2. struct rebind
  3. { typedef typename _Base_type::template rebind_alloc<_Tp> other; };

等价于

  1. typename __gnu_cxx::__alloc_traits<_Alloc>::template rebind<_Tp>::other

等价于:

  1. typename _Base_type::template rebind_alloc<_Tp>

_Base_type是:

  1. typedef std::allocator_traits<_Alloc> _Base_type;

所以上述等价于:

  1. typename std::allocator_traits<_Alloc>::template rebind_alloc<_Tp>

继续到allocator_traits中寻找

找到了:

  1. template<typename _Up>
  2. using rebind_alloc = allocator<_Up>;

于是:

  1. std::allocator_traits<_Alloc>::template rebind_alloc<_Tp>

等价于:

  1. allocator<_Tp>

小结

  1. typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template rebind<_Tp>::other _Tp_alloc_type;

等价于:

  1. typedef allocator<_Tp> _Tp_alloc_type

1.2 pointer

pointer

  1. typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type>::pointer
  2. pointer;

等价于:

  1. typedef typename __gnu_cxx::__alloc_traits<allocator<_Tp>>::pointer
  2. pointer;

根据下面两行:

  1. typedef std::allocator_traits<_Alloc> _Base_type;
  2. typedef typename _Base_type::pointer pointer;

又等价于:

  1. typedef std::allocator_traits<_Alloc>::pointer
  2. pointer;

allocator_traits中找到下面:

  1. /**
  2. * @brief The allocator's pointer type.
  3. *
  4. * @c Alloc::pointer if that type exists, otherwise @c value_type*
  5. */
  6. typedef __pointer pointer;

注释中说了如果存在就是Alloc::pointer,否则为value_type *

小结

  1. typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type>::pointer
  2. pointer;
  3. // 或者
  4. typedef typename __gnu_cxx::__alloc_traits<allocator<_Tp>>::pointer
  5. pointer;

等价于

  1. /**
  2. * @brief The allocator's pointer type.
  3. *
  4. * @c Alloc::pointer if that type exists, otherwise @c value_type*
  5. */
  6. typedef __pointer pointer;

如果存在_Tp_alloc_type::pointer也就是allocator<_Tp>存在就是allocator<_Tp>::pointer

这个看allocator.h源码:

  1. typedef _Tp* pointer;

否则为value_type*。而value_type为:

  1. typedef typename _Alloc::value_type value_type;

所以value_type*推导出为:

  1. _Tp::value_type*

1.3 vector的内存管理

_Vector_base中有一个内存管理器_Vector_impl类,该结构体继承allocator(根据上述1.1等价条件得出)。

  1. template<typename _Tp, typename _Alloc>
  2. struct _Vector_base {
  3. //__alloc_traits -> allocator_traits
  4. // typedef allocator<_Tp> _Tp_alloc_type
  5. typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
  6. rebind<_Tp>::other _Tp_alloc_type;
  7. // _Tp::value_type* or _Tp*
  8. typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type>::pointer
  9. pointer;
  10. struct _Vector_impl
  11. : public _Tp_alloc_type {
  12. pointer _M_start; // 使用空间起始位置
  13. pointer _M_finish; // 使用空间结束位置
  14. pointer _M_end_of_storage; // 可使用空间结束位置
  15. _Vector_impl()
  16. : _Tp_alloc_type(), _M_start(0), _M_finish(0), _M_end_of_storage(0) {}
  17. _Vector_impl(_Tp_alloc_type const &__a)
  18. // vector数据交换,只交换内存地址,不交换数据
  19. void _M_swap_data(_Vector_impl &__x)
  20. _GLIBCXX_NOEXCEPT
  21. {
  22. std::swap(_M_start, __x._M_start);
  23. std::swap(_M_finish, __x._M_finish);
  24. std::swap(_M_end_of_storage, __x._M_end_of_storage);
  25. }
  26. };
  27. public:
  28. typedef _Alloc allocator_type;
  29. // 前面我们知道_Vector_impl继承自allocator分配器,而这个又是_Tp_alloc_type,所以这里返回的就是_M_impl的基类。
  30. _Tp_alloc_type &
  31. _M_get_Tp_allocator()
  32. _GLIBCXX_NOEXCEPT
  33. { return *static_cast<_Tp_alloc_type *>(&this->_M_impl); }
  34. const _Tp_alloc_type &
  35. _M_get_Tp_allocator() const
  36. _GLIBCXX_NOEXCEPT
  37. { return *static_cast<const _Tp_alloc_type *>(&this->_M_impl); }
  38. allocator_type // 获取传递进来的分配器
  39. get_allocator() const
  40. _GLIBCXX_NOEXCEPT
  41. { return allocator_type(_M_get_Tp_allocator()); }
  42. _Vector_base()
  43. : _M_impl() {}
  44. _Vector_base(const allocator_type &__a)
  45. _GLIBCXX_NOEXCEPT
  46. : _M_impl(__a) {}
  47. _Vector_base(size_t __n)
  48. : _M_impl() { _M_create_storage(__n); }
  49. _Vector_base(size_t __n, const allocator_type &__a)
  50. : _M_impl(__a) { _M_create_storage(__n); }
  51. #if __cplusplus >= 201103L
  52. _Vector_base(_Tp_alloc_type&& __a) noexcept
  53. : _M_impl(std::move(__a)) { }
  54. // 移动构造函数,只交换3个指针,不copy数据
  55. _Vector_base(_Vector_base&& __x) noexcept
  56. : _M_impl(std::move(__x._M_get_Tp_allocator()))
  57. { this->_M_impl._M_swap_data(__x._M_impl); }
  58. _Vector_base(_Vector_base&& __x, const allocator_type& __a)
  59. : _M_impl(__a)
  60. {
  61. if (__x.get_allocator() == __a)
  62. this->_M_impl._M_swap_data(__x._M_impl);
  63. else
  64. {
  65. size_t __n = __x._M_impl._M_finish - __x._M_impl._M_start;
  66. _M_create_storage(__n);
  67. }
  68. }
  69. #endif
  70. ~_Vector_base()
  71. _GLIBCXX_NOEXCEPT
  72. {
  73. _M_deallocate(this->_M_impl._M_start, this->_M_impl._M_end_of_storage
  74. - this->_M_impl._M_start);
  75. }
  76. public:
  77. _Vector_impl _M_impl;
  78. pointer _M_allocate(size_t __n) {
  79. typedef __gnu_cxx::__alloc_traits <_Tp_alloc_type> _Tr;
  80. return __n != 0 ? _Tr::allocate(_M_impl, __n) : 0; // 同_M_deallocate,一直往后调用的就是malloc函数
  81. }
  82. void _M_deallocate(pointer __p, size_t __n) {
  83. typedef __gnu_cxx::__alloc_traits <_Tp_alloc_type> _Tr;
  84. if (__p)
  85. _Tr::deallocate(_M_impl, __p, __n); // 最后调用allocator_traits的deallocate,而该函数又是根据传递进来的_M_impl进行deallocate,一直往后,最后调用的就是free函数
  86. }
  87. private:
  88. void _M_create_storage(size_t __n) {
  89. this->_M_impl._M_start = this->_M_allocate(__n);
  90. this->_M_impl._M_finish = this->_M_impl._M_start;
  91. this->_M_impl._M_end_of_storage = this->_M_impl._M_start + __n;
  92. }
  93. };

小结:_Vector_base专门负责vector的内存管理,内部类_M_impl通过继承_Tp_alloc_type(也就是allocator)得到内存分配释放的功能,_M_allocate和_M_deallocate分别分配和释放vector所用内存,vector只需要负责元素构造和析构。

在vector中,默认内存分配器为std::allocator<_Tp>

  1. template<typename _Tp, typename _Alloc = std::allocator<_Tp>>
  2. class vector : protected _Vector_base<_Tp, _Alloc> {
  3. }

vector代码中使用基类的内存函数及typedef等:

  1. template<typename _Tp, typename _Alloc = std::allocator<_Tp>>
  2. class vector : protected _Vector_base<_Tp, _Alloc> {
  3. typedef _Vector_base<_Tp, _Alloc> _Base;
  4. typedef typename _Base::_Tp_alloc_type _Tp_alloc_type;
  5. public:
  6. typedef typename _Base::pointer pointer;
  7. protected:
  8. using _Base::_M_allocate;
  9. using _Base::_M_deallocate;
  10. using _Base::_M_impl;
  11. using _Base::_M_get_Tp_allocator;
  12. }

2.vector迭代器

在vector中使用了两种迭代器,分别是正向__normal_iterator与反向迭代器reverse_iterator:

正向:

  1. typedef __gnu_cxx::__normal_iterator <pointer, vector> iterator;
  2. typedef __gnu_cxx::__normal_iterator <const_pointer, vector> const_iterator;

反向:

  1. typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
  2. typedef std::reverse_iterator<iterator> reverse_iterator;

__normal_iteratorreverse_iterator都定义于stl_iterator.h,封装了vector元素的指针。

2.1 正向

  1. template<typename _Iterator, typename _Container>
  2. class __normal_iterator
  3. {
  4. protected:
  5. _Iterator _M_current;
  6. typedef iterator_traits<_Iterator> __traits_type;
  7. public:
  8. typedef _Iterator iterator_type;
  9. // iterator必须包含的五种typedef
  10. typedef typename __traits_type::iterator_category iterator_category;
  11. typedef typename __traits_type::value_type value_type;
  12. typedef typename __traits_type::difference_type difference_type;
  13. typedef typename __traits_type::reference reference;
  14. typedef typename __traits_type::pointer pointer;
  15. _GLIBCXX_CONSTEXPR __normal_iterator() _GLIBCXX_NOEXCEPT
  16. : _M_current(_Iterator()) { }
  17. explicit
  18. __normal_iterator(const _Iterator& __i) _GLIBCXX_NOEXCEPT
  19. : _M_current(__i) { }
  20. // Allow iterator to const_iterator conversion
  21. template<typename _Iter>
  22. __normal_iterator(const __normal_iterator<_Iter,
  23. typename __enable_if<
  24. (std::__are_same<_Iter, typename _Container::pointer>::__value),
  25. _Container>::__type>& __i) _GLIBCXX_NOEXCEPT
  26. : _M_current(__i.base()) { }
  27. // Forward iterator requirements
  28. reference
  29. operator*() const _GLIBCXX_NOEXCEPT
  30. { return *_M_current; }
  31. pointer
  32. operator->() const _GLIBCXX_NOEXCEPT
  33. { return _M_current; }
  34. // 前置++
  35. __normal_iterator&
  36. operator++() _GLIBCXX_NOEXCEPT
  37. {
  38. ++_M_current;
  39. return *this;
  40. }
  41. // 后置++
  42. __normal_iterator
  43. operator++(int) _GLIBCXX_NOEXCEPT
  44. { return __normal_iterator(_M_current++); }
  45. // 前置--
  46. // Bidirectional iterator requirements
  47. __normal_iterator&
  48. operator--() _GLIBCXX_NOEXCEPT
  49. {
  50. --_M_current;
  51. return *this;
  52. }
  53. // 后置--
  54. __normal_iterator
  55. operator--(int) _GLIBCXX_NOEXCEPT
  56. { return __normal_iterator(_M_current--); }
  57. // 随机访问迭代器都要重载[]操作符
  58. // Random access iterator requirements
  59. reference
  60. operator[](difference_type __n) const _GLIBCXX_NOEXCEPT
  61. { return _M_current[__n]; }
  62. // +=操作符 跳跃n个difference_type
  63. __normal_iterator&
  64. operator+=(difference_type __n) _GLIBCXX_NOEXCEPT
  65. { _M_current += __n; return *this; }
  66. // +操作符 跳跃n个difference_type
  67. __normal_iterator
  68. operator+(difference_type __n) const _GLIBCXX_NOEXCEPT
  69. { return __normal_iterator(_M_current + __n); }
  70. // -=操作符 后退n个difference_type
  71. __normal_iterator&
  72. operator-=(difference_type __n) _GLIBCXX_NOEXCEPT
  73. { _M_current -= __n; return *this; }
  74. // -操作符 后退n个difference_type
  75. __normal_iterator
  76. operator-(difference_type __n) const _GLIBCXX_NOEXCEPT
  77. { return __normal_iterator(_M_current - __n); }
  78. const _Iterator&
  79. base() const _GLIBCXX_NOEXCEPT
  80. { return _M_current; }
  81. };

_M_current是指向迭代器位置的指针,这是一个随机访问型指针,operator+和operator-等移动操作可以直接移动到目的地,非随机访问型指针只能一步步移动。

2.2 反向

vector还会使用reverse_iterator,即逆序迭代器,顾名思义,其移动方向与普通迭代器相反

  1. template<typename _Iterator>
  2. class reverse_iterator
  3. : public iterator<typename iterator_traits<_Iterator>::iterator_category,
  4. typename iterator_traits<_Iterator>::value_type,
  5. typename iterator_traits<_Iterator>::difference_type,
  6. typename iterator_traits<_Iterator>::pointer,
  7. typename iterator_traits<_Iterator>::reference>
  8. {
  9. protected:
  10. _Iterator current;
  11. typedef iterator_traits<_Iterator> __traits_type;
  12. public:
  13. typedef _Iterator iterator_type;
  14. typedef typename __traits_type::difference_type difference_type;
  15. typedef typename __traits_type::pointer pointer;
  16. typedef typename __traits_type::reference reference;
  17. // 省略不重要的代码
  18. // 该迭代器是从后面end()开始,需要往前一步,才可以获取到有效的迭代器位置
  19. reference
  20. operator*() const
  21. {
  22. _Iterator __tmp = current;
  23. return *--__tmp;
  24. }
  25. // 通过调用上述*操作符直接实现
  26. pointer
  27. operator->() const
  28. { return &(operator*()); }
  29. // 前置++操作符完成后退任务
  30. reverse_iterator&
  31. operator++()
  32. {
  33. --current;
  34. return *this;
  35. }
  36. // 后置++
  37. reverse_iterator
  38. operator++(int)
  39. {
  40. reverse_iterator __tmp = *this;
  41. --current;
  42. return __tmp;
  43. }
  44. // 前置--操作符完成前进任务
  45. reverse_iterator&
  46. operator--()
  47. {
  48. ++current;
  49. return *this;
  50. }
  51. // 后置--
  52. reverse_iterator
  53. operator--(int)
  54. {
  55. reverse_iterator __tmp = *this;
  56. ++current;
  57. return __tmp;
  58. }
  59. // +操作符
  60. reverse_iterator
  61. operator+(difference_type __n) const
  62. { return reverse_iterator(current - __n); }
  63. // +=操作符
  64. reverse_iterator&
  65. operator+=(difference_type __n)
  66. {
  67. current -= __n;
  68. return *this;
  69. }
  70. // -操作符
  71. reverse_iterator
  72. operator-(difference_type __n) const
  73. { return reverse_iterator(current + __n); }
  74. // -=操作符
  75. reverse_iterator&
  76. operator-=(difference_type __n)
  77. {
  78. current += __n;
  79. return *this;
  80. }
  81. // []操作符
  82. reference
  83. operator[](difference_type __n) const
  84. { return *(*this + __n); }
  85. };

3.vector的数据结构

vector内存由_M_impl中的M_start,_M_finish,_M_end_of_storage三个指针管理,所有关于地址,容量大小等操作都需要用到这三个指针:

  1. iterator begin() _GLIBCXX_NOEXCEPT
  2. { return iterator(this->_M_impl._M_start); }
  3. iterator end() _GLIBCXX_NOEXCEPT
  4. { return iterator(this->_M_impl._M_finish); }
  5. reverse_iterator rbegin() noexcept
  6. { return reverse_iterator(end()); }
  7. reverse_iterator rend() noexcept
  8. { return reverse_iterator(begin()); }
  9. size_type size() const _GLIBCXX_NOEXCEPT
  10. { return size_type(this->_M_impl._M_finish - this->_M_impl._M_start); }
  11. size_type capacity() const _GLIBCXX_NOEXCEPT
  12. { return size_type(this->_M_impl._M_end_of_storage - this->_M_impl._M_start); }
  13. bool empty() const _GLIBCXX_NOEXCEPT
  14. { return begin() == end(); }

vector_1.png

_M_finish和_M_end_of_storage之间的空间没有数据,有时候这是一种浪费,c++11提供了一个很有用的函数shrink_to_fit(),将这段未使用空间释放,主要调用了下面代码,

  1. template<typename _Alloc>
  2. bool vector<bool, _Alloc>::
  3. _M_shrink_to_fit()
  4. {
  5. if (capacity() - size() < int(_S_word_bit)) // 64位系统为64bytes
  6. return false;
  7. __try
  8. {
  9. _M_reallocate(size());
  10. return true;
  11. }
  12. __catch(...)
  13. {
  14. return false;
  15. }
  16. }
  1. template<typename _Alloc>
  2. void vector<bool, _Alloc>::
  3. _M_reallocate(size_type __n)
  4. {
  5. _Bit_type* __q = this->_M_allocate(__n);
  6. this->_M_impl._M_finish = _M_copy_aligned(begin(), end(),
  7. iterator(__q, 0));
  8. this->_M_deallocate();
  9. this->_M_impl._M_start = iterator(__q, 0);
  10. this->_M_impl._M_end_of_storage = __q + _S_nword(__n);
  11. }

_M_copy_aligned通过两个std::copy实现:

第一次swap把first的指针与last的指针之间的数据拷贝到result指针所指向的起始位置。第二次swap获得last的指针对应的迭代器。

  1. iterator
  2. _M_copy_aligned(const_iterator __first, const_iterator __last,
  3. iterator __result)
  4. {
  5. // _Bit_type * _M_p; _Bit_type为unsigned long类型
  6. _Bit_type* __q = std::copy(__first._M_p, __last._M_p, __result._M_p);
  7. return std::copy(const_iterator(__last._M_p, 0), __last,
  8. iterator(__q, 0));
  9. }

先分配size()大小的内存空间,用于存储begin()end()之间的数据,释放原来的vector空间,新的vector只包含size()数量的数据,并修改_M_start_M_end_of_storage指向。

4.vector构造与析构

  1. //使用默认内存分配器
  2. vector() : _Base() { }
  3. //指定内存分配器
  4. explicit vector(const allocator_type& __a) : _Base(__a) { }
  5. //初始化为n个__value值,如果没指定就使用该类型默认值
  6. explicit vector(size_type __n, const value_type& __value = value_type(),
  7. const allocator_type& __a = allocator_type()): _Base(__n, __a)
  8. { _M_fill_initialize(__n, __value); }
  9. //拷贝构造函数
  10. vector(const vector& __x)
  11. : _Base(__x.size(),
  12. _Alloc_traits::_S_select_on_copy(__x._M_get_Tp_allocator()))
  13. { this->_M_impl._M_finish =
  14. std::__uninitialized_copy_a(__x.begin(), __x.end(),
  15. this->_M_impl._M_start,
  16. _M_get_Tp_allocator());
  17. }
  18. //c++11的移动构造函数,获取__x的M_start,_M_finish,_M_end_of_storage,并不需要数据拷贝
  19. vector(vector&& ) noexcept
  20. : _Base(std::move(__x)) { }
  21. //从list中拷贝数据,也是c++11才有的
  22. vector(initializer_list<value_type> __l,
  23. const allocator_type& __a = allocator_type())
  24. : _Base(__a)
  25. {
  26. _M_range_initialize(__l.begin(), __l.end(), random_access_iterator_tag());
  27. }
  28. //支持vector使用两个迭代器范围内的值初始化,除了stl的迭代器,也可以是数组地址
  29. template<typename _InputIterator,
  30. typename = std::_RequireInputIter<_InputIterator>>
  31. vector(_InputIterator __first, _InputIterator __last,
  32. const allocator_type& __a = allocator_type())
  33. : _Base(__a)
  34. { _M_initialize_dispatch(__first, __last, __false_type()); }
  35. //只析构所有元素,释放内存由vector_base完成
  36. ~vector() _GLIBCXX_NOEXCEPT
  37. { std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,_M_get_Tp_allocator()); }

5.vector

插入涉及到内存分配,动态调整,与一开始提到的vector与array区别,就在下面体现出:

  1. typename vector<_Tp, _Alloc>::iterator
  2. vector<_Tp, _Alloc>::insert(iterator __position, const value_type& __x)
  3. {
  4. const size_type __n = __position begin();
  5. //插入到最后一个位置,相当于push_back
  6. if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage
  7. && __position == end())
  8. {
  9. _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, __x);
  10. ++this->_M_impl._M_finish;
  11. }
  12. else
  13. {
  14. _M_insert_aux(__position, __x);
  15. }
  16. return iterator(this->_M_impl._M_start + __n);
  17. }

其中_M_insert_aux实现:

  1. template<typename _Tp, typename _Alloc>
  2. void vector<_Tp, _Alloc>::_M_insert_aux(iterator __position, const _Tp& __x)
  3. {
  4. //内存空间足够
  5. if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage)
  6. {
  7. _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish,
  8. _GLIBCXX_MOVE(*(this->_M_impl._M_finish
  9. - 1)));
  10. ++this->_M_impl._M_finish;
  11. //__position后的元素依次向后移动一个位置
  12. _GLIBCXX_MOVE_BACKWARD3(__position.base(),
  13. this->_M_impl._M_finish - 2,
  14. this->_M_impl._M_finish 1);
  15. //目标地址赋值
  16. *__position = _Tp(std::forward<_Args>(__args)...);
  17. }
  18. else
  19. {
  20. //内存加倍
  21. const size_type __len =
  22. _M_check_len(size_type(1), "vector::_M_insert_aux");
  23. const size_type __elems_before = __position - begin();
  24. pointer __new_start(this->_M_allocate(__len));
  25. pointer __new_finish(__new_start);
  26. __try
  27. {
  28. //给position位置赋值
  29. _Alloc_traits::construct(this->_M_impl,
  30. __new_start + __elems_before,
  31. std::forward<_Args>(__args)...);
  32. __x);
  33. __new_finish = 0;
  34. //拷贝position位置前元素
  35. __new_finish = std::__uninitialized_move_if_noexcept_a
  36. (this->_M_impl._M_start, __position.base(),
  37. __new_start, _M_get_Tp_allocator());
  38. ++__new_finish;
  39. //拷贝position位置后元素
  40. __new_finish
  41. = std::__uninitialized_move_if_noexcept_a
  42. (__position.base(), this->_M_impl._M_finish,
  43. __new_finish, _M_get_Tp_allocator());
  44. }
  45. __catch(...)
  46. {
  47. if (!__new_finish)
  48. _Alloc_traits::destroy(this->_M_impl,
  49. __new_start + __elems_before);
  50. else
  51. std::_Destroy(__new_start, __new_finish, _M_get_Tp_allocator());
  52. _M_deallocate(__new_start, __len);
  53. __throw_exception_again;
  54. }
  55. //析构原vector所有元素
  56. std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
  57. _M_get_Tp_allocator());
  58. //释放原vector内存空间
  59. _M_deallocate(this->_M_impl._M_start,
  60. this->_M_impl._M_end_of_storagethis->_M_impl._M_start);
  61. //vector内存地址指向新空间
  62. this->_M_impl._M_start = __new_start;
  63. this->_M_impl._M_finish = __new_finish;
  64. this->_M_impl._M_end_of_storage = __new_start + __len;
  65. }
  66. }

其中_M_check_len

  1. size_type
  2. _M_check_len(size_type __n, const char* __s) const
  3. {
  4. if (max_size() - size() < __n)
  5. __throw_length_error(__N(__s));
  6. const size_type __len = size() + std::max(size(), __n); //如果n小于当前size,内存加倍,否则内存增长n。
  7. return (__len < size() || __len > max_size()) ? max_size() : __len;
  8. }

内存分配策略并不是简单的加倍,如果n小于当前size,内存加倍,否则内存增长n。

学习资料:

侯捷《STL源码剖析》

https://www.cnblogs.com/coderkian/p/3888429.html