std::vector
's reallocation policy still unclearSection: 23.3.11.3 [vector.capacity] Status: Open Submitter: Daniel Krügler Opened: 2009-04-20 Last modified: 2020-07-17
Priority: 3
View other active issues in [vector.capacity].
View all other issues in [vector.capacity].
View all issues with Open status.
Discussion:
I have the impression that even the wording of current draft
N2857
does insufficiently express the intent of vector
's
reallocation strategy. This has produced not too old library
implementations which release memory in the clear()
function
and even modern articles about C++ programming cultivate
the belief that clear
is allowed to do exactly this. A typical
example is something like this:
const int buf_size = ...; std::vector<T> buf(buf_size); for (int i = 0; i < some_condition; ++i) { buf.resize(buf_size); write_or_read_data(buf.data()); buf.clear(); // Ensure that the next round get's 'zeroed' elements }
where still the myth is ubiquitous that buf
might be
allowed to reallocate it's memory inside the for
loop.
IMO the problem is due to the fact, that
std::vector
is explained in 23.3.11.3 [vector.capacity]/3 and /6 which
are describing just the effects of the reserve
function, but in many examples (like above) there
is no explicit call to reserve
involved. Further-more
23.3.11.3 [vector.capacity]/6 does only mention insertions
and never mentions the consequences of erasing elements.
the effects clause of std::vector
's erase
overloads in
23.3.11.5 [vector.modifiers]/4 is silent about capacity changes. This
easily causes a misunderstanding, because the counter
parting insert functions described in 23.3.11.5 [vector.modifiers]/2
explicitly say, that
Causes reallocation if the new size is greater than the old capacity. If no reallocation happens, all the iterators and references before the insertion point remain valid.
It requires a complex argumentation chain about four
different places in the standard to provide the — possibly
weak — proof that calling clear()
also does never change
the capacity of the std::vector
container. Since std::vector
is the de-facto replacement of C99's dynamic arrays this
type is near to a built-in type and it's specification should
be clear enough that usual programmers can trust their
own reading.
[ Batavia (2009-05): ]
Bill believes paragraph 1 of the proposed resolution is unnecessary because it is already implied (even if tortuously) by the current wording.
Move to Review.
[ 2009-10 Santa Cruz: ]
Mark as NAD. Rationale: there is no consensus to clarify the standard, general consensus that the standard is correct as written.
[2020-05-08; Reopen after reflector discussions]
"correct as written" has been disputed.
[2020-07-17; Priority set to 3 in telecon]
Proposed resolution:
[
This is a minimum version. I also
suggest that the wording explaining the allocation strategy
of std::vector
in 23.3.11.3 [vector.capacity]/3 and /6 is moved into
a separate sub paragraph of 23.3.11.3 [vector.capacity] before
any of the prototype's are discussed, but I cannot provide
reasonable wording changes now.
]
Change 23.3.11.3 [vector.capacity]/6 as follows:
It is guaranteed that no reallocation takes place during insertions or erasures that happen after a call to
reserve()
until the time when an insertion would make the size of the vector greater than the value ofcapacity()
.
Change 23.3.11.5 [vector.modifiers]/4 as follows:
Effects: The capacity shall remain unchanged and no reallocation shall happen. Invalidates iterators and references at or after the point of the erase.