vector的性能利器:reserve

轉載請註明文章出處:tlanyan.me/reserve-of-…ios

vectorC++編程時的經常使用容器,其幫助用戶自動管理存儲空間,簡單易用,且能避免資源泄露的問題。須要動態分配存儲空間的場景,徹底可替代原生數組。c++

vector被人詬病的地方在於性能。C++ 11引入array容器,有原生數組的性能,編譯期能肯定大小的狀況可取代vector。但對於運行期才能肯定大小的狀況,array不適用,仍是得上vector編程

實踐中提升vector性能的要點是儘可能使用reserve(僅次於換編譯器和STL實現)。運行期依然不能肯定數組的個數,明智的選擇是什麼也不作,push_back/emplace_back就足夠;運行期能肯定個數,則應該用reserve,不建議用傳遞大小的數組構造函數或者調用resize數組

reserve vs resize

reserveresize函數都能分配足夠容納下指定個數對象的空間。不一樣之處是resize(或構造函數傳遞數組個數)會改變數組的size(即當前元素的指針),而且極大的可能性會調用存儲對象的**(複製)構造函數**。reserve作的事情就比較純粹:僅分配所需的空間。函數

一段代碼說明三者的區別:性能

// file: test.cpp
#include <iostream>
#include <vector>


class Foo {
    public:
        Foo() {
            std::cout << "Foo constructor" << std::endl;
        }
};

int main(int argc, char* argv[]) {
    std::cout << "initialize vector with element number..." << std::endl;
    std::vector<Foo> vec1(5);
    std::cout << "-------------" << std::endl;
    std::cout << "vec1 size:" << vec1.size() << std::endl << std::endl;

    std::cout << "vector resize..." << std::endl;
    std::vector<Foo> vec2;
    vec2.resize(5);
    std::cout << "-------------" << std::endl;
    std::cout << "vec2 size:" << vec2.size() << std::endl << std::endl;


    std::cout << "vector reserve..." << std::endl;
    std::vector<Foo> vec3;
    vec3.reserve(5);
    std::cout << "-------------" << std::endl;
    std::cout << "vec3 size:" << vec3.size() << std::endl << std::endl;

    return 0;
}
複製代碼

gcc編譯程序:g++ -std=c++0x -o test -O2 test.cpp,而後./test執行程序,結果以下:spa

initialize vector with element number...
Foo constructor
Foo constructor
Foo constructor
Foo constructor
Foo constructor
-------------
vec1 size:5

vector resize...
Foo constructor
Foo constructor
Foo constructor
Foo constructor
Foo constructor
-------------
vec2 size:5

vector reserve...
-------------
vec3 size:0
複製代碼

輸出結果很顯然:不管用構造數組時指定個數,仍是resize,都會調用存儲類型的默認構造函數並改變size。常規狀況下,默認生成的對象沒什麼用處,最後都會被覆蓋掉。若是存儲類型的構造函數比較複雜,這兩種方式都以大代價作無用功。指針

reserve就不會,理念簡單,性能槓槓的。code

注意:編譯上述程序,去掉-std=c++0x選項,結果將會不一樣。緣由是vector的構造函數或者resize默認用複製的方式填充,因此構造函數僅調用一次。server

總結

細心對比,你會發現reserveresize的區別就像mallocnew的區別(不過malloc是函數,new是操做符):malloc/operator new/reserve獲得一塊冰冷的內存,什麼都沒有;new/resize獲得的是一個個鮮活的對象。若是僅需存儲空間的話,malloc/operator new會更高效。

因此,使用vector時儘可能用reserver來提升性能。

參考

  1. std::vector::resize
  2. Does the vector.resize() method calls the default elements constructors when resizing?
相關文章
相關標籤/搜索