329. vector capacity, reserve and reallocation

Section: 26.3.11.3 [vector.capacity], 26.3.11.5 [vector.modifiers] Status: CD1 Submitter: Anthony Williams Opened: 2001-07-13 Last modified: 2016-02-10

Priority: Not Prioritized

View all other issues in [vector.capacity].

View all issues with CD1 status.

Discussion:

There is an apparent contradiction about which circumstances can cause a reallocation of a vector in Section 26.3.11.3 [vector.capacity] and section 26.3.11.5 [vector.modifiers].

26.3.11.3 [vector.capacity],p5 says:

Notes: Reallocation invalidates all the references, pointers, and iterators referring to the elements in the sequence. 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 size specified in the most recent call to reserve().

Which implies if I do

  std::vector<int> vec;
  vec.reserve(23);
  vec.reserve(0);
  vec.insert(vec.end(),1);

then the implementation may reallocate the vector for the insert, as the size specified in the previous call to reserve was zero.

However, the previous paragraphs (26.3.11.3 [vector.capacity], p1-2) state:

(capacity) Returns: The total number of elements the vector can hold without requiring reallocation

...After reserve(), capacity() is greater or equal to the argument of reserve if reallocation happens; and equal to the previous value of capacity() otherwise...

This implies that vec.capacity() is still 23, and so the insert() should not require a reallocation, as vec.size() is 0. This is backed up by 26.3.11.5 [vector.modifiers], p1:

(insert) Notes: Causes reallocation if the new size is greater than the old capacity.

Though this doesn't rule out reallocation if the new size is less than the old capacity, I think the intent is clear.

Proposed resolution:

Change the wording of 26.3.11.3 [vector.capacity] paragraph 5 to:

Notes: Reallocation invalidates all the references, pointers, and iterators referring to the elements in the sequence. 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().

[Redmond: original proposed resolution was modified slightly. In the original, the guarantee was that there would be no reallocation until the size would be greater than the value of capacity() after the most recent call to reserve(). The LWG did not believe that the "after the most recent call to reserve()" added any useful information.]

Rationale:

There was general agreement that, when reserve() is called twice in succession and the argument to the second invocation is smaller than the argument to the first, the intent was for the second invocation to have no effect. Wording implying that such cases have an effect on reallocation guarantees was inadvertant.