Why vector hold a class type will call the copy constructor one more time when push_back()?

前端 未结 2 2064
佛祖请我去吃肉
佛祖请我去吃肉 2021-01-23 04:50

I have the following code:

#include 
using std::cin; using std::cout; using std::endl;
#include 
using std::vector;

class Quote {
         


        
相关标签:
2条回答
  • 2021-01-23 05:09

    As per C++ language open standard draft n3690.pdf regarding vector capacity. Please see the bold italicized statement.

    23.3.7.3 vector capacity [vector.capacity] size_type capacity() const noexcept; 1 Returns: The total number of elements that the vector can hold without requiring reallocation. void reserve(size_type n); 2 Requires: T shall be MoveInsertable into *this. 3 Effects: A directive that informs a vector of a planned change in size, so that it can manage the storage allocation accordingly. After reserve(), capacity() is greater or equal to the argument of reserve if reallocation happens; and equal to the previous value of capacity() otherwise. "Reallocation happens at this point if and only if the current capacity is less than the argument of reserve()". If an exception is thrown other than by the move constructor of a non-CopyInsertable type, there are no effects

    Also from Scott Meyers "Effective C++ Digital Collection: 140 Ways to Improve Your Programming", under item 14 Item 14.

    Use reserve to avoid unnecessary reallocations. One of the most marvelous things about STL containers is that they automatically grow to accommodate as much data as you put into them, provided only that you don't exceed their maximum size. (To discover this maximum, just call the aptly named max_size member function.) For vector and string, growth is handled by doing the moral equivalent of a realloc whenever more space is needed. This realloc-like operation has four parts: 1. Allocate a new block of memory that is some multiple of the container's current capacity. In most implementations, vector and string capacities grow by a factor of between 1.5 and 2 each time.

    As suggested by "songyuanyao" one should reserve the size(if it is known in advance) to avoid frequent reallocation.

    0 讨论(0)
  • 2021-01-23 05:18

    When the push_back is called at the 2nd time, reallocation happened. (More precisely it happens when the new size() is greater than capacity().) Then the old underlying storage of the vector will be destroyed and the new one will be allocated, and elements need to be copied to the new storage, which cause the copy constructor to be called.

    You can use reserve to avoid reallocation. e.g.

    vector<Quote> basket;
    basket.reserve(2);
    basket.push_back(Quote("0-201-82470-1", 50));
    basket.push_back(Quote("0-201-82XXXXX", 30)); // no reallocation here
    
    0 讨论(0)
提交回复
热议问题