码迷,mamicode.com
首页 > 其他好文 > 详细

STL源码剖析(4):容器(vector)

时间:2015-06-19 16:51:52      阅读:101      评论:0      收藏:0      [点我收藏+]

标签:stl   源码   容器   vector   

  容器是很多人对STL的第一印象,vector,stack,queue,set,map等等都是容器。
  这里先介绍 STL中的序列式容器。
  所谓序列式容器,其中的元素可序(ordered),但未必有序(sorted)。C++ 本身提供了一个序列式容器——数组(array),STL中还提供了向量(vector),链表(list),堆栈(stack),队列(queue),优先队列(priority queue)等,其中stack和queue只是将deque(双端队列)设限而得到的,技术上可以被归为一种配接器(adaptor)。

Vector:
  vector的数据安排以及操作方式与array非常相似,两者的唯一差别在于空间的运用的灵活性。array是静态空间,一旦配置了就不能改变。vector是动态空间,随着元素的加入,它的内部机制会自行扩充空间以容纳新元素。因此,vector对内存的运用更加有效,更加有效。Vector的实现技术,关键是对大小的控制以及重新配置时的数据移动效率,主要分为三个步骤:配置新空间,数据移动,释放旧空间。
  Vector内部结构为:

template <class T, class Alloc = alloc>
class vector {
public:
  typedef T value_type;
  typedef value_type* pointer;
  typedef const value_type* const_pointer;
  typedef value_type* 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;

protected:
  typedef simple_alloc<value_type, Alloc> data_allocator;
  iterator start;
  iterator finish;
  iterator end_of_storage;
};

  vector使用的线性连续空间,其中start是目前使用空间的头,finish是目前使用空间的为尾,end_of_storage是可使用空间的尾。为了降低空间配置时的速度成本,vector实际配置的大小可能比目前vector存储的数据所需的空间要大,以备将来的扩充。如果满载并有新元素加入,就另觅新居。
  vector维护的是一个连续线性空间,所以无论其元素型别为何,普通指针都可以作为vector的迭代器。因为vector迭代器所执行的操作行为,如operator*,operator->,operator++,operator–,operator+,operator-,operator+=,operator-=,普通指针天生就具备。所以,vector提供的是Random Access Iterator。
  vector若空间不够,在动态增长时,并不是在原来空间之后接续新空间,而是以原大小的两倍配置一块较大空间,然后将原内容拷贝过来。因此,对vector的任何操作,一旦引起空间的重新配置,指向原vector的所有迭代器就都失效了。
 
  来看下vector几个常用操作的源码:

void push_back(const T& x) {
    if (finish != end_of_storage) { //空间未满
      construct(finish, x); //直接构造
      ++finish;
    }
    else //空间不够
      insert_aux(end(), x);
}
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;
  }
  void pop_back() {
    --finish;
    destroy(finish); //析构
}
template <class T, class Alloc>
void vector<T, Alloc>::insert_aux(iterator position, const T& x) {
  if (finish != end_of_storage) { //空间未满
    construct(finish, *(finish - 1)); //插入要增加一个元素,所以先在末尾新构造一个
    ++finish;
    T x_copy = x;
    copy_backward(position, finish - 2, finish - 1); //从position往后移动一个位置
    *position = x_copy; //插入
  }
  else {
    const size_type old_size = size(); //当前的空间大小
    const size_type len = old_size != 0 ? 2 * old_size : 1; //新的空间大小,为以前的两倍
    iterator new_start = data_allocator::allocate(len);//分配新的空间
    iterator new_finish = new_start;
    __STL_TRY {
      new_finish = uninitialized_copy(start, position, new_start); //复制position之前的数据
      construct(new_finish, x); //插入新元素
      ++new_finish;
      new_finish = uninitialized_copy(position, finish, new_finish); //复制position之后的数据
    }
    destroy(begin(), end());//析构原来的元素
    deallocate();//释放原来的空间
    start = new_start;
    finish = new_finish;
    end_of_storage = new_start + len;
  }
}

  其中copy_backward()代码如下:

template <class BidirectionalIterator1, class BidirectionalIterator2>
inline BidirectionalIterator2 __copy_backward(BidirectionalIterator1 first, 
                                              BidirectionalIterator1 last, 
                                              BidirectionalIterator2 result) {
  while (first != last) *--result = *--last;
  return result;
}

其他常见操作:
Iterators:
begin:Return iterator to beginning (public member function )
end:Return iterator to end (public member function )

Capacity:
size:Return size (public member function )
capacity:Return size of allocated storage capacity (public member function )
empty:Test whether vector is empty (public member function )

Element access:
operator[]:Access element (public member function )
at:Access element (public member function )
front:Access first element (public member function )
back:Access last element (public member function )
data:Access data (public member function )

Modifiers:
push_back:Add element at the end (public member function )
pop_back:Delete last element (public member function )
insert:Insert elements (public member function )
erase:Erase elements (public member function )
swap:Swap content (public member function )
clear:Clear content (public member function )
emplace :Construct and insert element (public member function )
emplace_back :Construct and insert element at the end (public member function )

STL源码剖析(4):容器(vector)

标签:stl   源码   容器   vector   

原文地址:http://blog.csdn.net/kzq_qmi/article/details/46561941

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!