Is it more efficient to preallocate a vector?

后端 未结 3 1969
野的像风
野的像风 2020-12-13 17:54

In C++ Primer fourth edition, by Stanley B.Lippman, Josee Lajoie and Barbara E. Moo it states:

Because vectors grow efficiently, it is usually best to

相关标签:
3条回答
  • 2020-12-13 18:26

    I timed this simple example:

    #include<iostream>
    #include<vector>
    
    int main() {
    
        int limit = 100 * 1000 * 1000;
        std::vector<long> my_vec;
        my_vec.reserve(limit); // comment out this line to not preallocate
    
        for (int i=0; i < limit; i++) {
            my_vec.push_back(i);
        }
    
        long my_sum = 0;
        for (int i=0; i < limit; i++) {
            my_sum += my_vec[i];
        }
    
        std::cout << my_sum << std::endl;
        return 0;
    }
    

    Complied with:

    g++ -std=c++11 -O2 my_file.cpp -o my_exec
    

    And found the difference to be substantial:

    Without preallocation:

    real    0m3.366s
    user    0m1.656s
    sys     0m1.660s
    

    With preallocation:

    real    0m1.688s
    user    0m0.732s
    sys     0m0.936s
    

    My conclusion here is: If building a vector is a big part of the program, then preallocating for efficiency makes sense. However, building a larger vector over and over is unlikely, and thus it is rarely a bottle neck. However, using reserve() has other advantages besides preallocating.

    Bjarne Stroustrup in The C++ programming language (4th addition) has this to say:

    I used to be careful about using reserve() when I was reading into a vector. I was surprised to find that for essentially all my uses, calling reserve() did not measurably affect performance. The default growth strategy worked just as well as my estimates, so I stopped trying to improve performance using reserve(). Instead I use it to increase predictability of reallocation delays and to prevent invalidation of pointers and iterators.

    0 讨论(0)
  • 2020-12-13 18:47

    It depends.

    If you don't know what the final size will be, then let the vector allocate using its allocation scheme (usually doubles each time, or somewhere around there). This way you avoid reallocating for every single element:

    std::vector<int> v;
    
    // good:
    for (/* populate v */) // unknown number of iterations
    {
        v.push_back(i); // possible reallocation, but not often
    }
    
    // bad:
    for (/* populate v */) // unknown number of iterations
    {
        v.reserve(v.size() + 1); // definite reallocation, every time
        v.push_back(i); // (no reallocation)
    }
    

    But if you know ahead of time you won't be reallocating, then preallocate:

    std::vector<int> v;
    
    // good:
    v.reserve(10); 
    for (/* populate v */) // only 10 iterations (for example)
    {
        v.push_back(i); // no reallocations
    }
    
    // not bad, but not the best:
    for (/* populate v */) // only 10 iterations (for example)
    {
        v.push_back(i); // possible reallocation, but not often (but more than needed!)
    }
    
    0 讨论(0)
  • 2020-12-13 18:52

    It can be. It depends a lot on what the elements are, how much work it is to copy or construct them, and how many there are.

    If you preallocate a vector you will end up calling the default constructor for each element to make empty elements, and then copying the item over the space later. If you add elements it can just copy or construct the element in place which may be more efficient.

    0 讨论(0)
提交回复
热议问题