STL源码剖析之vector

    1.vector

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

    开头处定义:

    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

    pointer

    1. typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type>::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*

    _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. }

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

    正向:

    1. typedef std::reverse_iterator<iterator> reverse_iterator;

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

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

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

    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. }
    80. // []操作符
    81. reference
    82. operator[](difference_type __n) const
    83. { return *(*this + __n); }
    84. };

    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(); }

    _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指向。

    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. }

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

    学习资料: