1. vector内存分配
《Effective STL》中“条款14”:使用reserve来避免不必要的重新分配
关于STL容器,最神奇的事情之一是只要不超过它们的最大大小,它们就可以自动增长到足以容纳你放进去的数据。(要知道这个最大值,只要调用名叫max_size的成员函数。)对于vector和string,只要需要更多空间,就以realloc等价的思想来增长。这个类似于realloc的操作有四个部分:
- 分配新的内存块,它有容器目前容量的几倍。在大部分实现中,vector和string的容量每次以2为因数增长。也就是说,当容器必须扩展时,它们的容量每次翻倍。
- 把所有元素从容器的旧内存拷贝到它的新内存。
- 销毁旧内存中的对象。
- 回收旧内存。
给了所有的分配,回收,拷贝和析构,你就应该知道那些步骤都很昂贵。当然,你不会想要比必须的更为频繁地执行它们。如果这没有给你打击,那么也许当你想到每次这些步骤发生时,所有指向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(); }