vector的内存分配与释放

  1. vector内存分配

《Effective STL》中“条款14”:使用reserve来避免不必要的重新分配

关于STL容器,最神奇的事情之一是只要不超过它们的最大大小,它们就可以自动增长到足以容纳你放进去的数据。(要知道这个最大值,只要调用名叫max_size的成员函数。)对于vector和string,只要需要更多空间,就以realloc等价的思想来增长。这个类似于realloc的操作有四个部分:

  1. 分配新的内存块,它有容器目前容量的几倍。在大部分实现中,vector和string的容量每次以2为因数增长。也就是说,当容器必须扩展时,它们的容量每次翻倍。
  2. 把所有元素从容器的旧内存拷贝到它的新内存。
  3. 销毁旧内存中的对象。
  4. 回收旧内存。

给了所有的分配,回收,拷贝和析构,你就应该知道那些步骤都很昂贵。当然,你不会想要比必须的更为频繁地执行它们。如果这没有给你打击,那么也许当你想到每次这些步骤发生时,所有指向vector或string中的迭代器、指针和引用都会失效时,它会给你打击的。这意味着简单地把一个元素插入vector或string的动作也可能因为需要更新其他使用了指向vector或string中的迭代器、指针或引用的数据结构而膨胀。

 DEMO

#include <QtCore/QCoreApplication>
#include <QDebug>
#include <vector>

using namespace std;

class Person
{
public:
        Person(QString str)
        {
            m_str=str;
            qDebug()<< "construction:"<<m_str;
        }
        Person(const Person& p)
        {
            this->m_str=p.m_str;
            qDebug()<< "copy construction:"<<m_str;
        }
        ~Person()
        {
            qDebug()<< "destruction:"<<m_str;
        }
    private:
        QString m_str;
};

int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);
    {
        vector<Person> V;
        //V.reserve(10);

        qDebug()<<"MaxSize :"<<V.max_size()<<"Capacity :"<<V.capacity();

        Person a("a");
        Person b("b");
        Person c("c");

        qDebug()<<"  push :a";
        V.push_back(a);
        qDebug()<<"Size :"<<V.size()<<"Capacity :"<<V.capacity();
        qDebug()<<"  push :b";
        V.push_back(b);
        qDebug()<<"Size :"<<V.size()<<"Capacity :"<<V.capacity();
        qDebug()<<"  push :c";
        V.push_back(c);
        qDebug()<<"Size :"<<V.size()<<"Capacity :"<<V.capacity();

        V.clear();
        qDebug()<<"Size :"<<V.size()<<"Capacity :"<<V.capacity();

        //
        //vector<Person>(V).swap(V);
        //qDebug()<<"Size :"<<V.size()<<"Capacity :"<<V.capacity();
    }

    return app.exec();
}

 

 

 

 

 

 

 

 

 

 

 

添加reserve:

V.reserve(10);

 

 

 

 

 

插入新项时就不用重新拷贝构造 b和c了,提高效率。

 

   2. vector内存释放

《Effective STL》中“条款17”:使用“交换技巧”来修整过剩容量

当vector、string大量插入数据后,即使删除了大量数据(或者全部都删除,即clear) 并没有改变容器的容量(capacity),所以仍然会占用着内存。 为了避免这种情况,我们应该想办法改变容器的容量使之尽可能小的符合当前 数据所需(shrink to fit)

《Effective STL》给出的解决方案是:

即先创建一个临时拷贝与原先的vector一致,值得注意的是,此时的拷贝 其容量是尽可能小的符合所需数据的。紧接着将该拷贝与原先的vector v进行 交换。好了此时,执行交换后,临时变量会被销毁,内存得到释放。此时的v即为原先 的临时拷贝,而交换后的临时拷贝则为容量非常大的vector(不过已经被销毁)

 

int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);
    {
        vector<int> V;

        for(int i=0;i<1000000;i++)
        {V.push_back(i);}
        qDebug()<<"Size :"<<V.size()<<"Capacity :"<<V.capacity();

        qDebug()<<"Clear:";
        V.clear();
        qDebug()<<"Size :"<<V.size()<<"Capacity :"<<V.capacity();

        qDebug()<<"Swap(V):";
        vector<int>(V).swap(V);
        qDebug()<<"Size :"<<V.size()<<"Capacity :"<<V.capacity();
    }
    return app.exec();
}

 

posted on 2016-12-14 14:48  五本百源  阅读(8202)  评论(0编辑  收藏  举报

导航