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