• STL—vector空间的动态增长


    vector空间的动态增长

        当添加元素时,如果vector空间大小不足,则会以原大小的两倍另外配置一块较大的新空间,然后将原空间内容拷贝过来,在新空间的内容末尾添加元素,并释放原空间。vector的空间动态增加大小,并不是在原空间之后的相邻地址增加新空间,因为vector的空间是线性连续分配的,不能保证原空间之后有可供配置的空间。因此,对vector的任何操作,一旦引起空间的重新配置,指向原vector的所有迭代器就会失效。
     

    vector的size(),capacity(),reserve(),resize()函数

        vector对象的内存布局如下图所示。
         start迭代器指向已用空间的首元素,finish指向已用空间的尾元素的下一个位置,end_of_storage指向可用空间的末尾。
         size()函数返回的是已用空间大小,capacity()返回的是总空间大小,capacity()-size()则是剩余的可用空间大小。当size()和capacity()相等,说明vector目前的空间已被用完,如果再添加新元素,则会引起vector空间的动态增长。
         由于动态增长会引起重新分配内存空间、拷贝原空间、释放原空间,这些过程会降低程序效率。因此,可以使用reserve(n)预先分配一块较大的指定大小的内存空间,这样当指定大小的内存空间未使用完时,是不会重新分配内存空间的,这样便提升了效率。只有当n>capacity()时,调用reserve(n)才会改变vector容量。
        resize()成员函数只改变元素的数目,不改变vector的容量。
     
    程序说明:
        分配了两个容器a,b。其中每次往a中添加1个元素,共添加10次。使用reserve()预先为b分配一块10个元素大小的空间,之后才每次往b中添加1个元素,共添加10次。当b空间满后,再往其中添加1个元素。之后使用reserve()为b分配一块15(比原空间小)个元素大小的空间。再使用resize()将b的元素个数改变为5个。
        观察上述过程中size()和capacity()大小的变化。
    #include <iostream>
    #include <vector>
    using namespace std;
    int main()
    {
        vector<int> a;
        cout << "a.size(): " << a.size() << "       a.capacity(): " << a.capacity() << endl;
        for (int i = 0; i < 10; i++)
        {
            a.push_back(i);
            cout << "a.size(): " << a.size() << "   a.capacity(): " << a.capacity() << endl;
        }
        cout << endl;
        vector<int> b;
        b.reserve(10);
        for (int i = 0; i < 10; i++)
        {
            b.push_back(i);
            cout << "b.size(): " << b.size() << "   b.capacity(): " << b.capacity() << endl;
        }
        b.push_back(11);
        cout << "b.size(): " << b.size() << "       b.capacity(): " << b.capacity() << endl;
        cout << endl;
        b.reserve(15);
        cout << "after b.reserve(15):" << endl;
        cout << "b.size(): " << b.size() << "       b.capacity(): " << b.capacity() << endl;
        b.resize(5);
        cout << "after b.resize(5):" << endl;
        cout << "b.size(): " << b.size() << "       b.capacity(): " << b.capacity() << endl;
        return 0;
    }
    输出:
    a.size(): 0     a.capacity(): 0
    a.size(): 1     a.capacity(): 1
    a.size(): 2     a.capacity(): 2
    a.size(): 3     a.capacity(): 4
    a.size(): 4     a.capacity(): 4
    a.size(): 5     a.capacity(): 8
    a.size(): 6     a.capacity(): 8
    a.size(): 7     a.capacity(): 8
    a.size(): 8     a.capacity(): 8
    a.size(): 9     a.capacity(): 16
    a.size(): 10    a.capacity(): 16
    b.size(): 1     b.capacity(): 10
    b.size(): 2     b.capacity(): 10
    b.size(): 3     b.capacity(): 10
    b.size(): 4     b.capacity(): 10
    b.size(): 5     b.capacity(): 10
    b.size(): 6     b.capacity(): 10
    b.size(): 7     b.capacity(): 10
    b.size(): 8     b.capacity(): 10
    b.size(): 9     b.capacity(): 10
    b.size(): 10    b.capacity(): 10
    b.size(): 11    b.capacity(): 20
    after b.reserve(15):
    b.size(): 11    b.capacity(): 20
    after b.resize(5):
    b.size(): 5     b.capacity(): 20
    现象:a重新分配空间共5次,每次都为之前空间的2倍。b在未超出reserve()预分配的空间时没有重新分配。
    结论:
        1. 空的vector对象,size()和capacity()都为0
        2. 当空间大小不足时,新分配的空间大小为原空间大小的2倍。
        3. 使用reserve()预先分配一块内存后,在空间未满的情况下,不会引起重新分配,从而提升了效率。
        4. 当reserve()分配的空间比原空间小时,是不会引起重新分配的。
        5. resize()函数只改变容器的元素数目,未改变容器大小。

    (全文完)

    附:
    一款简易版STL的实现,项目地址:https://github.com/zinx2016/MiniSTL/tree/master/MiniSTL
     
     
     
  • 相关阅读:
    基于麦克风阵列的声源定位算法之GCC-PHAT
    Parametric and Non-parametric Algorithms
    MATLAB中运算符优先级
    [HAOI2018]染色
    [SHOI2016]黑暗前的幻想乡
    [SCOI2012]滑雪
    [PA2014]Kuglarz
    Stroll
    [SDOI2010]大陆争霸
    解决IDEA Gradle构建报错"Cause: zip END header not found"
  • 原文地址:https://www.cnblogs.com/zxiner/p/7197327.html
Copyright © 2020-2023  润新知