vector的内存分配与释放

时间:2022-01-26 18:30:32

  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();
}

vector的内存分配与释放

添加reserve:

V.reserve();

vector的内存分配与释放

插入新项时就不用重新拷贝构造 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=;i<;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();
}

vector的内存分配与释放