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?
相关文章
相关标签/搜索