您的位置:首页 > 其它

STL源码分析之Vector

2012-05-13 19:52 585 查看
                                                                                                                             STL源码分析之Vector

地球人都知道vector的查找效率很高, 插入和删除的效率低下, 容器会随着元素的不断增加自动增长, 最近在看了STL源码之后, 发现确实是这样, 下面是vector一些关键的函数. 从这些函数可以看出插入和删除的过程, 以及容器自动增长的方式.

 

// 两个通过下标获取元素的函数.

reference operator[](size_type __n) { return *(begin() + __n); }

const_reference operator[](size_type __n) const { return *(begin() + __n); }

 

// 给vector重新开拓空间n, 如果n小于原来的capacity就不进行处理

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);  // 分配__n空间,并把start到finish内容拷入

    destroy(_M_start, _M_finish);                                     // 销毁原来start到finish的空间

    _M_deallocate(_M_start, _M_end_of_storage - _M_start);            //

    _M_start = __tmp;                                                 // 重定向start

    _M_finish = __tmp + __old_size;                                   // 重定向finish

    _M_end_of_storage = _M_start + __n;                               // 重定向end_of_storage

  }

}

// 这个函数很关键, vector插入的效率和增长过程在这里体现出来

// 在position位置插入元素__x, 从中可以看出vector的插入需要移动元素, 效率比list低

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));                   // 最后一个元素后移

    ++_M_finish;                                              // finish iterator后移

    _Tp __x_copy = __x;                                       // while (first != last) *--result = *--last;

    copy_backward(__position, _M_finish - 2, _M_finish - 1);  // first = position, last = finish - 2, result = finish -1

    *__position = __x_copy;                                   // 把first 到 last - 1 处元素移到result - 1处

  }                                                           // 这样first即position处就空出来可以存放x

  else {

    const size_type __old_size = size();                            // 记录原来的size

    const size_type __len = __old_size != 0 ? 2 * __old_size : 1;   // 如果size不为0, 则默认再扩展2倍, 如果为0, 则是先分配1

    iterator __new_start = _M_allocate(__len);                      // 整个增长过程就是1、2、4、8、16

    iterator __new_finish = __new_start;

    __STL_TRY {                                                     // try 宏定义

      __new_finish = uninitialized_copy(_M_start, __position, __new_start);  // 把start到position的元素先放入新分配的空间

      construct(__new_finish, __x);                                          // new (__new_finish) (T) (__X)

      ++__new_finish;                                                        // 插入元素

      __new_finish = uninitialized_copy(__position, _M_finish, __new_finish);  // 把position到finish之间的元素继续插入, 完成__x插入过程

    }

    __STL_UNWIND((destroy(__new_start,__new_finish),                         // catch异常之后删除已经分配的内存

                  _M_deallocate(__new_start,__len)));                        // 析构函数p->~T()

    destroy(begin(), end());

    _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 push_back(const _Tp& __x) {

  if (_M_finish != _M_end_of_storage) {   //  如果vector尚有空间, 直接在finish位置构造x, finish往后移

    construct(_M_finish, __x);            // new (_M_finish) (T) (__x)

    ++_M_finish;                          // finish后移

  }

  else

    _M_insert_aux(end(), __x);            // 分配空间并在末端插入元素x

}

// 在vector __position的位置插入__x

iterator insert(iterator __position, const _Tp& __x) {

  size_type __n = __position - begin();

  if (_M_finish != _M_end_of_storage && __position == end()) {  // 如果是在末端插入元素而且vector还有空间, 直接插入

    construct(_M_finish, __x);

    ++_M_finish;

  }

  else _M_insert_aux(__position, __x);

  return begin() + __n;

}

 

// 在position 后面插入n个值为__x的元素, 如果内存不够, vector会默认分配大于2倍目前size的空间

// 插入完元素之后会把原来内存删除

template <class _Tp, class _Alloc>

void vector<_Tp, _Alloc>::_M_fill_insert(iterator __position, size_type __n,

                                         const _Tp& __x)

{

  if (__n != 0) {

    if (size_type(_M_end_of_storage - _M_finish) >= __n) {         // 如果尚有空间容纳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);   // 把finish-n至finish右移n个位置, 空出n个位置

        _M_finish += __n;

        copy_backward(__position, __old_finish - __n, __old_finish); // 把position到finish-n位置的元素右移n个位置, 这样position

        fill(__position, __position + __n, __x_copy);                // 到finish所有元素已经右移动了n个位置, 再把n个元素插入初始化

      }

      else {

        uninitialized_fill_n(_M_finish, __n - __elems_after, __x_copy); // 把finish后面n - elems位置放置n - elems个x元素

        _M_finish += __n - __elems_after;

        uninitialized_copy(__position, __old_finish, _M_finish); // 把position至原来finish处所有元素移动至新finish后面

        _M_finish += __elems_after;

        fill(__position, __old_finish, __x_copy);                // 把position至原来finish处所有元素初始化为x

      }

    }

    else {                                                       // 需要分配空间

      const size_type __old_size = size();       

      const size_type __len = __old_size + max(__old_size, __n); // 新分配空间>= 2 * size()

      iterator __new_start = _M_allocate(__len);

      iterator __new_finish = __new_start;

      __STL_TRY {

        __new_finish = uninitialized_copy(_M_start, __position, __new_start); // 把start至position所有元素移动至新分配的内存空间

        __new_finish = uninitialized_fill_n(__new_finish, __n, __x);          // postion至position + n放置n个x元素

        __new_finish

          = uninitialized_copy(__position, _M_finish, __new_finish);           // position + n后面放置原来position至原来finish所有元素

      }

      __STL_UNWIND((destroy(__new_start,__new_finish),

                    _M_deallocate(__new_start,__len)));

      destroy(_M_start, _M_finish);                                            // p->~T()

      _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;

    }

  }

}

// 删除最后一个元素

void pop_back() {

  --_M_finish;

  destroy(_M_finish);  // p->~T();

}

// 删除position位置元素, 缺点, 需要移动position后面所有元素

iterator erase(iterator __position) {

  if (__position + 1 != end())                   // 如果不是最后一个元素, 把position + 1到finish之间的元素往前移一位

    copy(__position + 1, _M_finish, __position);

  --_M_finish;                                   // finish 往后移一位

  destroy(_M_finish);                            // 析构, p->~T()

  return __position;

}

// 删除first到last之间的元素, 缺点, 需要一抖last以后所有元素 

iterator erase(iterator __first, iterator __last) {

  iterator __i = copy(__last, _M_finish, __first);  // last到finish之间的元素移动到first开始处

  destroy(__i, _M_finish);

  _M_finish = _M_finish - (__last - __first);

  return __first;

}

// 把vector大小调整为new size, 如果小于原有size, 直接把后面元素删除, 如果大于, 则用x初始化后面分配的空间

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

// clear实际调用erase把所有元素删除掉

void clear() { erase(begin(), end()); }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: