STL学习——Vector篇

STL学习——Vector篇

  • vector简介

    vector的数据安排及操作方式与array非常相似,两者的区别在于空间运用的灵活性。array是静态空间,一旦配置了,就不能改变;要换个大(或小)一点的可以,但琐碎的事由客户端完成:首先配置一块新空间,然后将元素从旧址一一搬往新址,再把原来的空间释还给系统。而vector是动态空间,随着元素的加入,它的内部机制会自动扩充空间以容纳新元素。它对内存的合理利用和灵活运用有很大的帮助。

    vector实现关键技术:对大小的控制以及重新配置时的数据移动效率,vector扩充空间是“配置新空间,移动数据,释还旧空间”的过程。

  • vector定义

    vector的定义主要包括分配空间,定义相应内部属性,定义基本方法等。

  • vector迭代器

    vector维护一个连续的空间,故不论其元素类型如何,普通指针都可以作为vector的迭代器,vector迭代器需要进行的操作主要包括:operator *,operator->,operator++,operator–,operator+,operator-,operator+=,operator-=等。vector支持随机存取,普通指针就能达到这一能力。故vector中提供Random Access Iterators。

  • vector数据结构

    vector数据结构为线性连续空间,存在两个迭代器start和finish,分别指向配置得来的连续空间中目前已经被使用的范围,并以迭代器end_of_storage指向整块连续空间(含备用空间)的尾端。

    为降低空间配置时的速度成本,vector实际配置大小可能比客户端要求量更大,以备将来扩充。即为容量。一个vector的容量永远大于或等于其大小。一旦容量等于大小,便是满载,下次增加新元素是,整个vector需另找空间。使用start,finish,end_of_storage三个迭代器,可以轻易地提供首尾标示,大小,容量,空容器判断,标注运算符([]),最前端元素,最后端元素等。

    vector的扩容原则:如果超过当时的容量,则容量会扩充至两倍,如果两倍容量仍不足,就扩张至足够大的容量

  • vector的构造和内存管理

    vector的构造和内存管理主要涉及到constructor和push_back函数。其内存分配主要使用data_allocatir函数,可以很方便的配置n个元素的空间。vector存在多个版本构造函数,其中一个构造函数允许指定空间大小和初始值。vector中的push_back函数实现将新元素插入vector尾端,该函数首先检查是否还有备用空间,如果有则直接在备用空间上构造元素,并调整迭代器finish,使vector变大。如果没有备用空间,则需要扩充空间(重新配置,移动数据,释放原空间)。

    注意:vector的动态增加大小,并不是在原空间之后接续新空间(因为无法保证原空间之后尚有可配置的空间),而是以原大小的两倍另配置一块较大空间,然后将原内容拷贝过来,然后才开始在原内容之后构造新元素,并释放原空间。故对vector的任何操作,一旦引起空间重新配置,则指向原vector的所有迭代器就都失效

  • vector的元素操作

    vector所提供的元素操作较多,主要包括push_back,pop_back,erase,clear,insert等等。其详细介绍见下面源码分析。

  • vector源码分析

    // vector类定义
    template <class _Tp, class _Alloc = __STL_DEFAULT_ALLOCATOR(_Tp) >
    class vector : protected _Vector_base<_Tp, _Alloc> 
    {
      // requirements:
    
      __STL_CLASS_REQUIRES(_Tp, _Assignable);
    
    private:
      typedef _Vector_base<_Tp, _Alloc> _Base;
    public:
      // vector的嵌套类型定义
      typedef _Tp value_type;                       // vector元素类型
      typedef value_type* pointer;                  // vector指针
      typedef const value_type* const_pointer;      // vector静态指针
      typedef value_type* iterator;                 // vector迭代器是普通指针
      typedef const value_type* const_iterator;     // vector迭代器静态指针
      typedef value_type& reference;                // vector引用
      typedef const value_type& const_reference;    // vector静态引用
      typedef size_t size_type;                     // vector尺寸
      typedef ptrdiff_t difference_type;            // vector类型
      typedef typename _Base::allocator_type allocator_type;
      allocator_type get_allocator() const { return _Base::get_allocator(); }
      ...
    protected:
    // 下面实简单的空间配置器
    #ifdef __STL_HAS_NAMESPACES
      using _Base::_M_allocate;
      using _Base::_M_deallocate;
      using _Base::_M_start;               // 表示目前使用空间的头
      using _Base::_M_finish;              // 表示目前使用空间的尾
      using _Base::_M_end_of_storage;      // 表示目前空间可用的尾
    #endif /* __STL_HAS_NAMESPACES */
    protected:
      // 插入辅助函数
      void _M_insert_aux(iterator __position, const _Tp& __x);
      void _M_insert_aux(iterator __position);
    public:
      // vector头节点元素
      iterator begin() { return _M_start; }
      const_iterator begin() const { return _M_start; }
      // vector尾节点元素
      iterator end() { return _M_finish; }
      const_iterator end() const { return _M_finish; }
      // vector逆转后的头结点
      reverse_iterator rbegin()
        { return reverse_iterator(end()); }
      const_reverse_iterator rbegin() const
        { return const_reverse_iterator(end()); }
      // vector逆转后的尾节点
      reverse_iterator rend()
        { return reverse_iterator(begin()); }
      const_reverse_iterator rend() const
        { return const_reverse_iterator(begin()); }
      // 返回当前对象的个数
      size_type size() const
        { return size_type(end() - begin()); }
      // 返回最大尺寸
      size_type max_size() const
        { return size_type(-1) / sizeof(_Tp); }
      // 返回重新分配内存最多能存储的对象个数
      size_type capacity() const
        { return size_type(_M_end_of_storage - begin()); }
      // 判断是否为空函数
      bool empty() const
        { return begin() == end(); }
      // vector取值操纵
      reference operator[](size_type __n) { return *(begin() + __n); }
      const_reference operator[](size_type __n) const { return *(begin() + __n); }
      // vector构造函数,允许指定vector大小n和初值value
      explicit vector(const allocator_type& __a = allocator_type())
        : _Base(__a) {}
    
      vector(size_type __n, const _Tp& __value,
             const allocator_type& __a = allocator_type()) 
        : _Base(__n, __a)
        { _M_finish = uninitialized_fill_n(_M_start, __n, __value); }
    
      explicit vector(size_type __n)
        : _Base(__n, allocator_type())
        { _M_finish = uninitialized_fill_n(_M_start, __n, _Tp()); }
    
      vector(const vector<_Tp, _Alloc>& __x) 
        : _Base(__x.size(), __x.get_allocator())
        { _M_finish = uninitialized_copy(__x.begin(), __x.end(), _M_start); }
      // 对于整型类型,不使用iterator
      template <class _InputIterator>
      vector(_InputIterator __first, _InputIterator __last,
             const allocator_type& __a = allocator_type()) : _Base(__a) {
        typedef typename _Is_integer<_InputIterator>::_Integral _Integral;
        _M_initialize_aux(__first, __last, _Integral());
      }
    
      template <class _Integer>
      void _M_initialize_aux(_Integer __n, _Integer __value, __true_type) {
        _M_start = _M_allocate(__n);
        _M_end_of_storage = _M_start + __n; 
        _M_finish = uninitialized_fill_n(_M_start, __n, __value);
      }
      // vector初始化辅助函数
      template <class _InputIterator>
      void _M_initialize_aux(_InputIterator __first, _InputIterator __last,
                             __false_type) {
        _M_range_initialize(__first, __last, __ITERATOR_CATEGORY(__first));
      }
    vector(const _Tp* __first, const _Tp* __last,
             const allocator_type& __a = allocator_type())
        : _Base(__last - __first, __a) 
        { _M_finish = uninitialized_copy(__first, __last, _M_start); }
    // 析构函数
    ~vector() { destroy(_M_start, _M_finish); }  
    ...
    // 配置空间并填满
    #ifdef __STL_MEMBER_TEMPLATES
      template <class _ForwardIterator>
      iterator _M_allocate_and_copy(size_type __n, _ForwardIterator __first, 
                                                   _ForwardIterator __last)
    {
        iterator __result = _M_allocate(__n);
        __STL_TRY {
          uninitialized_copy(__first, __last, __result);
          return __result;
        }
        __STL_UNWIND(_M_deallocate(__result, __n));
      }
    #else /* __STL_MEMBER_TEMPLATES */
      iterator _M_allocate_and_copy(size_type __n, const_iterator __first, 
                                                   const_iterator __last)
      {
        iterator __result = _M_allocate(__n);
        __STL_TRY {
          uninitialized_copy(__first, __last, __result);
          return __result;
        }
        __STL_UNWIND(_M_deallocate(__result, __n));
      }
    #endif /* __STL_MEMBER_TEMPLATES */ 
    ...
    reference front() { return *begin(); }                 // 第一个元素
      const_reference front() const { return *begin(); }
      reference back() { return *(end() - 1); }              // 最后一个元素
      const_reference back() const { return *(end() - 1); }
    
      void push_back(const _Tp& __x) {           // 将元素插入值最尾端
        if (_M_finish != _M_end_of_storage) {    // 还有备用空间
          construct(_M_finish, __x);             // 全局函数
          ++_M_finish;                           // 调整水位高度
        }
        else                                     // 无备用空间
          _M_insert_aux(end(), __x);             // 该函数是vector的一个成员函数
      }
      void push_back() {
        if (_M_finish != _M_end_of_storage) {
          construct(_M_finish);
          ++_M_finish;
        }
        else
          _M_insert_aux(end());
      }
    ... 
     // 从position开始插入n个元素,元素初值为x
      void insert (iterator __pos, size_type __n, const _Tp& __x)
        { _M_fill_insert(__pos, __n, __x); }
    
      void _M_fill_insert (iterator __pos, size_type __n, const _Tp& __x);   // 见下面分析
      // 将尾端元素拿掉,并调整大小
      void pop_back() {                                  // 将最尾端元素取出
        --_M_finish;                                     // 将尾端标记往前一个格,表示将放弃尾端元素
        destroy(_M_finish);                              // destroy是全局函数
      }
      // 清除某个位置上的元素
      iterator erase(iterator __position) {              // 清除某位置上的元素
        if (__position + 1 != end())
          copy(__position + 1, _M_finish, __position);   // 后续元素往前移
        --_M_finish;
        destroy(_M_finish);
        return __position;
      }
      // 清除[first,last)中的所有元素
      iterator erase(iterator __first, iterator __last) {
        iterator __i = copy(__last, _M_finish, __first); // copy是全局函数
        destroy(__i, _M_finish);
        _M_finish = _M_finish - (__last - __first);
        return __first;
      }
      // 调整vector大小
      void resize(size_type __new_size, const _Tp& __x) {
        if (__new_size < size()) 
          erase(begin() + __new_size, end());
        else
          insert(end(), __new_size - size(), __x);
      }
      void resize(size_type __new_size) { resize(__new_size, _Tp()); }
      // 清除vector中元素
      void clear() { erase(begin(), end()); }
    ... 
    
    template <class _Tp, class _Alloc>
    void 
    vector<_Tp, _Alloc>::_M_insert_aux(iterator __position, const _Tp& __x)
    {
      if (_M_finish != _M_end_of_storage) {                       // 还有备用空间
        construct(_M_finish, *(_M_finish - 1));                   // 在备用空间起始处构造一个元素,并以vector最后一个元素值为其初始化
        ++_M_finish;                                              // 调整水位
        _Tp __x_copy = __x;
        copy_backward(__position, _M_finish - 2, _M_finish - 1);
        *__position = __x_copy;
      }
      else {                                                      // 无备用空间
        const size_type __old_size = size();
        const size_type __len = __old_size != 0 ? 2 * __old_size : 1;
        // 以上配置原则:如果原大小为0,则配置1(个元素大小);
        // 如果原大小不为0,则配置原大小的两倍,
        // 前半段用来放置原数据,后半段准备用来放置新数据
        iterator __new_start = _M_allocate(__len);                // 实际配置
        iterator __new_finish = __new_start;
        __STL_TRY {
          __new_finish = uninitialized_copy(_M_start, __position, __new_start);     // 将原vector的内容拷贝到新vector
          construct(__new_finish, __x);                                             // 为新元素设定初值x
          ++__new_finish;                                                           // 调整水位
          __new_finish = uninitialized_copy(__position, _M_finish, __new_finish);   // 将安插点的原内容也拷贝过来
        }
        __STL_UNWIND((destroy(__new_start,__new_finish), 
                      _M_deallocate(__new_start,__len)));
        destroy(begin(), end());                                                    // 析构并释放原vector
        _M_deallocate(_M_start, _M_end_of_storage - _M_start);
        _M_start = __new_start;                                                     // 调整迭代器,指向新vector
        _M_finish = __new_finish;
        _M_end_of_storage = __new_start + __len;
      }
    }
    // 从position开始,插入n个元素,元素初值为x
    template <class _Tp, class _Alloc>
    void vector<_Tp, _Alloc>::_M_fill_insert(iterator __position, size_type __n, 
                                             const _Tp& __x)
    {
      if (__n != 0) {                                                       // 当n!=0才进行以下所有操作
        if (size_type(_M_end_of_storage - _M_finish) >= __n) {              // 备用空间大于等于新增元素个数
          _Tp __x_copy = __x;                                               
          const size_type __elems_after = _M_finish - __position;           // 计算插入点之后的现有元素个数
          iterator __old_finish = _M_finish;                       
          if (__elems_after > __n) {                                        // 插入点之后的现有元素个数大于新增元素个数
            uninitialized_copy(_M_finish - __n, _M_finish, _M_finish);      
            _M_finish += __n;                                               // 将vector尾端标记后移
            copy_backward(__position, __old_finish - __n, __old_finish);
            fill(__position, __position + __n, __x_copy);                   // 插入点之后开始填入新值
          }
          else {                                                            // 插入点之后的现有元素个数小于等于新增元素个数                                                           
            uninitialized_fill_n(_M_finish, __n - __elems_after, __x_copy); 
            _M_finish += __n - __elems_after;
            uninitialized_copy(__position, __old_finish, _M_finish);
            _M_finish += __elems_after;
            fill(__position, __old_finish, __x_copy);
          }
        }
        else {    // 备用空间小于新增元素个数(必须配置额外的内存),首先决定新长度:旧长度的两倍,或旧长度+新增元素个数
          const size_type __old_size = size();        
          const size_type __len = __old_size + max(__old_size, __n);
          // 以下配置新的vector空间
          iterator __new_start = _M_allocate(__len);
          iterator __new_finish = __new_start;
          __STL_TRY {
            // 以下首先将旧的vector的插入点之前的元素复制到新空间
            __new_finish = uninitialized_copy(_M_start, __position, __new_start);
            // 以下再将新增元素(初值皆为n)填入新空间
            __new_finish = uninitialized_fill_n(__new_finish, __n, __x);
            // 以下再将旧vector的插入点之后的元素复制到新空间
            __new_finish
              = uninitialized_copy(__position, _M_finish, __new_finish);
          }
          __STL_UNWIND((destroy(__new_start,__new_finish), 
                        _M_deallocate(__new_start,__len)));
          // 以下清除并释放旧的vector
          destroy(_M_start, _M_finish);
          _M_deallocate(_M_start, _M_end_of_storage - _M_start);
          // 以下调整水位标记
          _M_start = __new_start;    
          _M_finish = __new_finish;
          _M_end_of_storage = __new_start + __len;
        }
      }
    }
    // vector逆转函数
    void reserve(size_type __n) {
      if (capacity() < __n) {
        const size_type __old_size = size();
        iterator __tmp = _M_allocate_and_copy(__n, _M_start, _M_finish);
        destroy(_M_start, _M_finish);
        _M_deallocate(_M_start, _M_end_of_storage - _M_start);
        _M_start = __tmp;
        _M_finish = __tmp + __old_size;
        _M_end_of_storage = _M_start + __n;
      }
    }
    
  • 参考文献

    STL源码剖析——侯捷
    STL源码

你可能感兴趣的:(vector,STL)