STL vector

分析的是sgi STL中vector的版本  http://www.sgi.com/tech/stl/download.html  作为学习之用
基础(SGI STL的空间分配器):
typedef __malloc_alloc_template<0> malloc_alloc;
..
# ifdef __USE_MALLOC
typedef malloc_alloc alloc; //令alloc为第一级配置器
#else
...
// 另外alloc为二级配置器
typedef __default_alloc_template<__NODE_ALLOCATOR_THREADS, 0> alloc;
不同的编译器能力不同所以对于预编译项__USE_MALLOC支持,g++默认是二级配置器,当然你也可以通过自己定义__USE_MALLOC来选择是否使用第一级。

对一级或者二级或者其他配置方式进行包装接口
template<class T, class Alloc>
class simple_alloc {
public:
    static T *allocate(size_t n)
                { return 0 == n? 0 : (T*) Alloc::allocate(n * sizeof (T)); }
    static T *allocate(void)
                { return (T*) Alloc::allocate(sizeof (T)); }
    static void deallocate(T *p, size_t n)
                { if (0 != n) Alloc::deallocate(p, n * sizeof (T)); }
    static void deallocate(T *p)
                { Alloc::deallocate(p, sizeof (T)); }
};

SGI STL第一级配置器:
template <int inst>
class __malloc_alloc_template {...};
其中:
1. allocate()直接调用malloc();
2. deallocate()直接使用的是free();
3. 模拟C++的set_new_handler以处理内存不足的情况 // 见Effective 条款7,operator new(执行分配内存不调用构造函数)使用的就是set_new_handler机制。

template <bool threads, int inst>
class __default_alloc_template {...};
其中:
1. 维护16个自由链表(free list) 8...128bytes的小额区块
如果区块超过128bytes时,移交给第一级配置器处理,当区块小于128bytes时,通过内存池(memory pool)管理(次级配置):每次配置一大块内存,并且维护相应的自由链表(free-lists).如果下次有相同大小的内存需求就直接从这里取;如果释放了内存,则放回到free-lists里面。对于任何的小额内存都会上调到8的倍数。
template <class T, class Alloc = alloc>
class vector {
public:
// 以下Iterator的五种嵌套型别定义,具体设计与作用可以看迭代器(Iterator)概念与traits编程技法
  typedef T value_type;
  typedef value_type* pointer;
  typedef const value_type* const_pointer;
  typedef value_type* iterator; // vector的iterator是原生指针,也就是vector提供的Random Access Iterator
  typedef const value_type* const_iterator;
  typedef value_type& reference;
  typedef const value_type& const_reference;
  typedef size_t size_type;
  typedef ptrdiff_t difference_type;
  /*
例子:客户端vector<int>::iterator it;
那么vector的iterator value_type就是int*; reference_type是int&;
*/
protected:

//simple_alloc见前文SGI STL的空间分配器部分,默认vector就是alloc配置器
  typedef simple_alloc<value_type, Alloc> data_allocator;  //于是data_allocator::allocate(n)表示的就是分配了n个元素空间
  iterator start;  //目前空间头
  iterator finish; // 目前空间尾
  iterator end_of_storage;//可用全部空间的尾巴
  void insert_aux(iterator position, const T& x);
  void deallocate() {
    if (start) data_allocator::deallocate(start, end_of_storage - start);
  }
  void fill_initialize(size_type n, const T& value) {
    start = allocate_and_fill(n, value);
    finish = start + n;
    end_of_storage = finish;
  }

//Public的类成员函数
public:
 iterator begin() { return start; }
  const_iterator begin() const { return start; }
  iterator end() { return finish; }
  const_iterator end() const { return finish; }
  reverse_iterator rbegin() { return reverse_iterator(end()); }
  const_reverse_iterator rbegin() const {
    return const_reverse_iterator(end());
  }
  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(T); }
  size_type capacity() const { return size_type(end_of_storage - begin()); }
  bool empty() const { return begin() == end(); }
  reference operator[](size_type n) { return *(begin() + n); }
  const_reference operator[](size_type n) const { return *(begin() + n); }
  vector() : start(0), finish(0), end_of_storage(0) {}
  vector(size_type n, const T& value) { fill_initialize(n, value); }  
/*
* fill_initialize函数首先会调用allocate配置n个元素空间,
然后调用全局函数uninitialized_fill_n来调用里面元素构造函数 
//  Vector<int> iv(2,9);这个对象的初始化过程,其中 end_of_storage为n即容量和size一样大
*/
  vector(int n, const T& value) { fill_initialize(n, value); }
  vector(long n, const T& value) { fill_initialize(n, value); }
  explicit vector(size_type n) { fill_initialize(n, T()); }
 // 拷贝构造函数的实现
  vector(const vector<T, Alloc>& x) {
/*
 template <class ForwardIterator>
 iterator allocate_and_copy(size_type n,
                             ForwardIterator first, ForwardIterator last) {
    iterator result = data_allocator::allocate(n);
   __STL_TRY {
     uninitialized_copy(first, last, result);
      return result;
    }
    __STL_UNWIND(data_allocator::deallocate(result, n));
  }
*/很清新的看到重新申请了内存,然后调用全局函数uninitialized_copy进行拷贝
    start = allocate_and_copy(x.end() - x.begin(), x.begin(), x.end());
    finish = start + (x.end() - x.begin());
    end_of_storage = finish;
  }
#ifdef __STL_MEMBER_TEMPLATES
  template <class InputIterator>
  vector(InputIterator first, InputIterator last) :
    start(0), finish(0), end_of_storage(0)
  {
    range_initialize(first, last, iterator_category(first));
  }
#else /* __STL_MEMBER_TEMPLATES */
  vector(const_iterator first, const_iterator last) {
    size_type n = 0;
    distance(first, last, n);
    start = allocate_and_copy(n, first, last);
    finish = start + n;
    end_of_storage = finish;
  }
#endif /* __STL_MEMBER_TEMPLATES */
  ~vector() {
    destroy(start, finish);
    deallocate();
  }
  vector<T, Alloc>& operator=(const vector<T, Alloc>& x);
  void reserve(size_type n) {
    if (capacity() < n) {
      const size_type old_size = size();
      iterator tmp = allocate_and_copy(n, start, finish);
      destroy(start, finish);
      deallocate();
      start = tmp;
      finish = tmp + old_size;
      end_of_storage = start + n;
    }
  }
  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 T& x) {
    if (finish != end_of_storage) {
      construct(finish, x); // construct全局函数,直接调用placement new;(元素的内存为finish所指向的内存,同时实现对其元素构造函数的调用)
      ++finish;
    }
    else
      insert_aux(end(), x);
  }
  void swap(vector<T, Alloc>& x) {
    __STD::swap(start, x.start);
    __STD::swap(finish, x.finish);
    __STD::swap(end_of_storage, x.end_of_storage);
  }
  iterator insert(iterator position, const T& x) {
    size_type n = position - begin();
    if (finish != end_of_storage && position == end()) {
      construct(finish, x);
      ++finish;
    }
    else
      insert_aux(position, x);
    return begin() + n;
  }
  iterator insert(iterator position) { return insert(position, T()); }
#ifdef __STL_MEMBER_TEMPLATES
  template <class InputIterator>
  void insert(iterator position, InputIterator first, InputIterator last) {
    range_insert(position, first, last, iterator_category(first));
  }
#else /* __STL_MEMBER_TEMPLATES */
  void insert(iterator position,
              const_iterator first, const_iterator last);
#endif /* __STL_MEMBER_TEMPLATES */
  void insert (iterator pos, size_type n, const T& x);
  void insert (iterator pos, int n, const T& x) {
    insert(pos, (size_type) n, x);
  }
  void insert (iterator pos, long n, const T& x) {
    insert(pos, (size_type) n, x);
  }
  void pop_back() {
    --finish;
    destroy(finish);
  }
  iterator erase(iterator position) {
    if (position + 1 != end())
      copy(position + 1, finish, position); //每一次erase需要调用copy导致position后面数据的移动
    --finish;
    destroy(finish);
    return position;
  }
  iterator erase(iterator first, iterator last) {
    iterator i = copy(last, finish, first);
    destroy(i, finish);
    finish = finish - (last - first);
    return first;
  }
  void resize(size_type new_size, const T& 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, T()); }
  void clear() { erase(begin(), end()); }

详细介绍insert函数的实现如下图文所示:

如下图4-3b-1所示的情况是,备用空间为2,新增元素也为2,所以,备用空间>=新增元素个数,而插入点之后的元素个数为3大于新增元素个数2(原有元素个数3个+备用空间为2,共5个存储单位)。此种情况的处理方式是,相当于将插入点之后的原有的3个元素整体向后移2个单位,然后把要新增的2个元素从插入点处插入,刚好满足新增的2个元素加上原有的3个元素共同存储在5个单位的空间中。


如下图4-3b-2所示,插入点之后的现有元素个数2<=新增元素个数3,此种情况的处理方式为:相当于将插入点之后的原有的3个元素整体向后移三个单位,然后把新增的3个元素从原插入点处插入:


如果原有空间不够,那么vector将实施所谓的动态增加大小,而动态增加大小,并不是指在原空间之后接连续新空间(因为无法保证原空间之后尚有可供配置的空间),而是以原大小的两倍另外配置一块较大空间,然后将原内容拷贝过来,然后才开始在原内容之后构造新元素,并释放原空间,这点可以从上述insert的实现中的第二部分,当借用空間小于「新增元素個數」(那就必须配置额外的内存)可以看出来。

如下图4-3b-3所示(另外,必须提醒的是,经过上述操作后,一旦引起空间重新配置,指向原vector的所有迭代器就都失效了。这是一般人会犯的错误,务必小心。 --侯捷如是说):


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值