66

This website implies that clearing a vector MAY change the capacity:

http://en.cppreference.com/w/cpp/container/vector/clear

Many implementations will not release allocated memory after a call to clear(), effectively leaving the capacity() of the vector unchanged.

But according to @JamesKanze this is wrong and the standard mandates that clear will not change capacity.

What does the standard say?

3
  • 1
    +1 others may run into this and be confused so good question. Commented Aug 27, 2013 at 14:16
  • 8
    en.cppreference.com/w/cpp/container/vector/clear has been updated to reflect @JamesKanze's answer below. Commented Aug 28, 2013 at 1:09
  • 2
    I came across the same question and was completely confused because cplusplus makes a strange statement about clear : "...and the vector capacity is not guaranteed to change" which I interpreted as: It might change but there is no guarantee that it does change. Commented May 4, 2016 at 17:47

2 Answers 2

77

Depending on the version of the standard you are looking at, clear is defined as the equivalent of erase(begin(), end()), or (in C++11):
"Destroys all elements in a. Invalidates all references, pointers, and iterators referring to the elements of a and may invalidate the past-the-end iterator."

In neither case is it allowed to modify the capacity; the following code is guaranteed safe by the standard:

std::vector<int> v;
for (int i = 0; i != 5; ++ i) {
    v.push_back(i);
}
assert(v.capacity() >= 5);
v.clear();
assert(v.capacity() >= 5);
v.push_back(10);
v.push_back(11);
std::vector<int>::iterator i = v.begin() + 1;
v.push_back(12);
v.push_back(13);
*i = 42;        //  i must still be valid, because none of 
                //  the push_back would have required an
                //  increase of capacity

(The reason for the change in wording in C++11: the committee didn't want to require MoveAssignable for clear, which would have been the case if it were defined in terms of erase.)

Sign up to request clarification or add additional context in comments.

25 Comments

@NeilKirk: If the capacity were to change, then it would break the guarantee offered by reserve: "It is guaranteed that no reallocation takes place during insertions that happen after a call to reserve() until the time when an insertion would make the size of the vector greater than the value of capacity()"
@NicolBolas That is precisely my point. The standard defines the observable behavior of a function, and that function cannot have any additional observable behavior. We take this for granted in a lot of cases: open will not reformat your disk, although I doubt you'll find a statement to that effect in the description (Posix or other) of open.
@MikeSeymour: By saying "Of course clear() isn't an insertion; but insertions after clear() are still subject to the guarantee, so clear() can't reduce the capacity.", does this mean that even copy/move assignment cannot reduce capacity (which I will be very surprised at)?
@MikeSeymour: I think the capacity() mentioned in the guarantee should be the value of capacity() upon the time of the insertion operation, not the the value of capacity() right after the reserve() call. So if clear() is allowed to shrink the capacity, the guarantee won't break. Whether clear() is allowed to shrink capacity or not is another question, I'm just saying that the justification you used here is not appropriate.
@JamesKanze: If we apply the no additional observable behavior other than specified rule (which I totally agree) to vector's copy/move assignment, can we come to the conclusion that copy/move assignment isn't allowed to reduce a vector's capacity either? This seems quite unreasonable. What went wrong here?
|
-1

I think the accepted answer is somewhat misleading.

clear() does not change capacity itself, but after clear() any other function call can shrink the capacity to 0, any assumption on capacity would become a trap in future modification.

3 Comments

… any other function call… Can you provide an example of what you mean?
@ENIAC For example, after v.clear() we have a function call doSth() and in doSth() there is a v.shrink_to_fit() which will make capacity to 0. So assumption on capacity after clear() is meaningless, if you want a certain capacity should call reserve() instead of assumption.
What happens after a function returns is irrelevant when discussing the behaviour of that function.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.