https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118293

            Bug ID: 118293
           Summary: Inserting at front of an empty deque shouldn't need to
                    allocate
           Product: gcc
           Version: 14.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libstdc++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: arthur.j.odwyer at gmail dot com
  Target Milestone: ---

https://godbolt.org/z/Y4nKfsfM8

int main() {
  std::deque<int> v;
  printf("Default-constructed capacity: %zu\n", capacity_of_v());
  v = {1};
  printf("Capacity after ={1}: %zu\n---\n", capacity_of_v());
}

prints:
  Default-constructed capacity: 128
  Capacity after ={1}: 256

That is, assigning into an empty deque caused the deque to allocate a second
block, even though the first, invariably-allocated block (bug #77524) was
completely available at that point.

This behavior comes from the test at the top of this member function:

      deque<_Tp, _Alloc>::
      _M_range_insert_aux(iterator __pos,
                          _ForwardIterator __first, _ForwardIterator __last,
                          std::forward_iterator_tag)
      [...]
        if (__pos._M_cur == this->_M_impl._M_start._M_cur)
          {
            iterator __new_start = _M_reserve_elements_at_front(__n);

That is, "if we're inserting at the front, then reserve elements at the front."
Either this check should be rewritten as "if we're inserting at the front AND
NOT AT THE BACK, then reserve elements at the front," or (if possible) the
"reserve elements at the front" action should be rewritten to try just bumping
the beginning forward in an empty deque instead of allocating a new block at
the front.

Reply via email to