Internal working of a vector in C++?
Im working on an exercise in C++ but im getting unexpected output I hope someone can explain. The exercise asked that I make a class called rock which has a default constructor, a copy constructor and a destructor all of which announce themselves to cout.
In the main method I am to try and add members of this class to a vector by value:
vector<Rock> byValue;
Rock r1, r2, r3;
byValue.push_back(r1);
byValue.push_back(r2);
byValue.push_back(r3);
cout <<开发者_StackOverflow; "byValue populated\n\n";
The output I expected (and shown in the exercise solutions) is:
Rock()
Rock()
Rock()
Rock(const Rock&)
Rock(const Rock&)
Rock(const Rock&)
byValue populated
~Rock()
~Rock()
~Rock()
~Rock()
~Rock()
~Rock()
However the output I get is:
Rock()
Rock()
Rock()
Rock(const Rock&)
Rock(const Rock&)
Rock(const Rock&)
~Rock()
Rock(const Rock&)
Rock(const Rock&)
Rock(const Rock&)
~Rock()
~Rock()
byValue populated
~Rock()
~Rock()
~Rock()
~Rock()
~Rock()
~Rock()
Can anyone explain why there seems to be extra calls to the copy constructor and destructor?
When the vector gets resized, the elements have to be moved to their new location.
This is normal.
If you call
byValue.reserve(10);
before any calls to push_back
, the extra copies should disappear.
A vector stores its elements contiguously. In order to avoid always re-allocating memory each time an element is inserted, it does allocate a bunch of memory. That is why vector has two methods regarding its "size": size()
which tells the number of elements stored, and capacity()
which indicates the amount of memory allocated.
Usually (but that is dependent on the STL implementation), it grows by doubling its precedent capacity. When it allocates more memory, and because data has to be stored contiguously (compared to a list
), it has to move its internal data; and the STL copies data, which is why you have so many calls to the constructor/destructor.
If you know how many elements will be stored in your vector, you can use reserve
to indicate how much memory it should allocated at first.
std::vector
has a limited amount of memory to store elements. You can query just how much with capacity
. You can also tell the vector to grab extra memory, with the reserve
method.
When you push an element onto the vector and its capacity is zero (it has used up all of it extra memory) it allocates a new larger array and copies the elements from the original. That is where all the extra copies are coming from.
Looking at your output it looks like the vector had to grow twice. If you changed to code to call reserve before pushing anything the vector would never need to grow and there would be no extra copies.
Here is a verbose code snippet that shows how all of this comes together: ideone.com
精彩评论