According to the C++ standard, is std::vector<T>::pop_back()
ever allowed to reduce the capacity of the vector?
I am asking because I would like to have a guarantee, that the following code will not throw an out of memory exception:
my_vec.pop_back();
if (...)
my_vec.push_back(...);
Assume that my_vec
is an std::vector<int>
.
I guess there are three possibilities:
Yes, this can happen according to both C++03 and C++11.
No, C++11 prohibits this (but C++03 does not).
No, both C++03 and C++11 prohibits this.
Yes, my question is related to Does std::vector.pop_back() change vector's capacity?, but my question is specifically about what the standard guarantees.
Note also that the accepted answer in Does std::vector.pop_back() change vector's capacity? is mostly about how to reduce the capacity of a vector, not about when it is guaranteed not to happen, and offers no evidence for its claim about pop_back().
No. The only way to shrink a vector's capacity is the swap trick, as shown here. And also the
C++11
way I mention bellow.Also, as the ref says:
In other words, it changes the size of the vector and not its capacity.
Take a look at the iterator validity:
In
C++11
you could usestd::vector<>::shrink_to_fit()
in order to change the capacity (for more see the 1st link). (tnx Psyduck). Interesting comments below the answer, but this question is not about the above method, so if interested, read the comments.Notice that even this method is not guaranteed to reduce the
capacity
, as the ref says:It would be too strange that this function is not guaranteed to reduce
capacity
andpop_back
does, while the ref of the second does not mentions anything relevant.The way I see it, since the ref does not mention
capacity
, this means that it's not needed to, which means, thatcapacity
remains the same.An interesting example is this:
Output:
where
capacity
is clearly not reduced.[EDIT]
Another relevant question, which could also be flagged as a duplicate has some good answers. Here are some interesting ones:
1)
2)
3)
I suggest reading the link for more.
[EDIT.2]
This question also supports that:
Q: Can
pop_back()
ever reduce thecapacity
?A: NO.
When you can't rely on the appropriate methods for reducing capacity (in terms of what you read in the standard), you can't expect
pop_back()
to do something like that.According to http://en.cppreference.com/w/cpp/container/vector/pop_back
Therefore it may not reallocate. There is no
C++11
tag on that page, which implies this is also true in 03. I will dig up the section references and edit them in for completeness.Edit: Even better: From
C++03
: [lib.container.requirements] (23.1), paragraph 10:Same wording at 23.2.1/10 in N3337 (~
C++11
).The comments are not really addressing it. Clearly, if std::vector is prohibited to use anything except std::allocator, and if std::allocator is prohibited to be extended with additional methods, then resizing with same base address is impossible, which makes it impossible to decrease capacity because iterators would be invalidated.
Closest info I could find about reallocation was a stackoverflow comment on Why is there no reallocation functionality in C++ allocators? saying
"There is nothing stopping std::vector from doing that in some cases (e.g., it knows its using the standard allocator). The standard library is allowed to use knowledge of the underlying system. – KeithB Jun 23 '10 at 21:39" (no references mentioned, though)
There have been submitted ideas for adding realloc to std::allocator, but they have both been rejected:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1953.html
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2045.html
The papers don't explicitly state that std::allocator is prohibited to extend std::allocator, though - they only state that it doesn't need to. They also don't explicitly state that std::vector is prohibited to use API calls to the underlying system... So no real info there either.