vector容器(或称vector类)将元素保存在连续的存储中。为了获得可接受的性能,vector会预先分配比所需元素更多的元素。每个将元素添加到容器的vector成员检查是否有可用空间以容纳新添加的元素。如果有,该成员在预分配的内存中下一可用位置初始化一个对象;如果没有,则重新分配vector。vector获取新的空间,将现存元素复制到新分配的空间,增加新元素,并释放旧空间。
vector所用存储开始是未构造内存,还没有存储任何对象。将元素复制或增加到这个预分配空间时,必须使用allocator类的construct成员构造元素。
以下以代码实现这个过程。
//pseduo-implementation of memory allocation strategy for vector container
template <class T> class vector {
public :
vector( ): M_start(0), M_finish(0), M_end_of_storage(0) {}
void push_back(const T&);
// ...
private:
static std::allocator<T> alloc; //object to get raw memory
void reallocate(); //get more space and copy existing element
T* M_start; //pointer to first element in the array
T* M_finish; //pointer to last element in the array
T* M_end_of_storage; //pointer to end of the space of vector
//....
};
可以使用这些指针来确定vector的大小和容量:
vector的size(实际使用)等于M_finish - M_start;
vector的capacity(在必须重新分配vector之前,可以定义的元素的综述)等于M_end_of_storage - M_start
自由空间(在需要重新分配之前,可以增加的元素的数目)是
M_end_of_storage - M_start
push_back成员使用这些指针将新元素添加到末尾
template <class T>
void vector<T>::push_back(const T& t)
{
//are we out of space?
if(M_finish == M_end_of_storage)
reallocate(); //gets more space and copies and existing elements
alloc.construct(M_finish, t);
++M_finish;
}
重新分配元素与复制元素
template <class T> void vector<T>::reallocate()
{
//compute size of current array and allocate space for twice as many elements
std::ptrdiff_t size = M_finish - M_start;
std::ptrdiff_t newcapacity = 2 * max(size,1);
//allocate space to hold newcapacity number of element of type T
T* newelements = alloc.allocate(newcapacity);
//construct copies of the existing elements in the new space
uninitialized_copy(M_start, M_finish, newelements);
//destory the old elemetn in reverse order
for(T *p = M_finish; p != M_start; /*empty*/)
alloc.destory(--p);
//deallocate cannot be called on a 0 pointer
if(M_start)
alloc.deallocate(M_start, M_end_of_storage-M_start)
//make our data structure point to the new elements
M_start = newelements;
M_finish = M_start +size;
M_end_of_storage = M_start + newcapacity;
}