STL vector的内存使用详解

vector的push_back()操作原理

      简单来说,push_back()就是往vector之后插入元素,这也是vector跟array最大的区别,array只能是固定大小,而有了vector之后,就可以动态扩大其容量了。下面解释一下vector插入时的一些基本原理。

vector中元素与待插入元素不是同一个对象:

      因为vector使用的alloc(用于分配内存)一直是从堆或者内存池(内存池应该是也属于堆)中获取内存,所以vector中所有的元素肯定不是位于栈上,就是我有一个int a=3,那么a肯定是位于栈上的,但是vectorb;b.push_back(a);之后,b[0]虽然值等于a,但是和a已经不是一个对象了,vector会在堆上给其重新分配内存。

vector的capacity属性

     vector的capacity属性可由vectorb;...;b.capacity()获得;代表了当前vector分配的大小;也就是当前vector中所能容纳的元素的个数。 b.capacity()>b.size(); vector在插入时,如果:插入数量+已有数量<=vector.capacity()就直接插入,而插入数量+已有数量>vector.capacity()时就需要申请更多的内存了。那么究竟是如何申请内存呢?

实验

我们会依次尝试向vector中插入元素。查看vector究竟是如何分配内存的。

#include                                                          
#include
using namespace std;

class A{ 
private:
    static int a; //标识A的数量   
public:
    A(){ 
        a++;
        cout<re;
     A s1;
    re.push_back(s1);
    //输出re分配的大小和首元素的地址
    cout<<"A capacity is :"<

实验结果

STL vector的内存使用详解_第1张图片

实验分析

      构造S1调用了普通构造函数,但是把他放入vector是调用的却是拷贝构造函数,而且拷贝构造函数构造出来的对象就是vector[0];
      构造S2是也是调用了普通构造函数,但却调用两次拷贝构造函数,和依次析构函数,显然可以看到析构掉的是之前的vector[0],而两个拷贝构造其中一个就是vector[0],那么另一个显然是vector1,就是新插入的元素。可以看出,当插入数量+已有数量>vector.capacity()时,系统会现将原有的vector中所有元素拷贝一份到新的地址中,然后将之前的vector中的元素全部析构掉。其实从《STL源码分析》中可以看到,此时vector中的start,finish和end_of_storage三个指针也同步更新了。
以此类推,我在最后依次插入S5的时候,因为5>re.capacity()=4,所以程序调用拷贝构造函数重新构造了之前的四个对象,当然刚开始还是构造了要push_back()进去的S5。最后再将之前的vector中的元素4个元素全部析构掉。

结论

      vector在插入元素的时候,首先调用拷贝构造函数在堆中申请内存构造对象,如果插入对象数量没有超过vector的capacity,就直接插入;若超过了就在调用拷贝构造函数将之前vector中所有的元素都重新构造一遍放入新的内存中,然后将之前vector中所有的元素全部析构掉,并释放内存。
 

clear()介

      函数clear()删除储存在vector中的所有元素. 如果vector的元素是一些object, 则它将为当前储存的每个元素调用它们各自的析构函数(destructor). 然而, 如果vector储存的是指向对象的指针, 此函数并不会调用到对应的析构函数. 在第二种情况下, 为了完全删除vector中的元素则应使用一个类似于下的循环:

    std::vector aVector;
    //The elements of the vector are created with the operand 'new' at some point in the program
    [...]
    for(int i=0 ; i


调用clear之后, vector的尺寸(size)将变成zero. 但它的容量(capacity)却并不发生变化, vector本身并不释放任何内存.

如果map,vector中存放了指针,指向手动分配的内存区域,则map,vector生命周期结束时,需要手动释放该内存区。map,vector的析构中带有垃圾回收机制,不需手动清空。记得,手动分配,才需手动清空。
 

你可能感兴趣的:(STL)