Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When shrinking a container via resize, in which order are the elements destroyed?

Tags:

c++

If I have a standard C++ container std::vector<Bar> and I shrink it by calling .resize() with a size smaller than the current .size(), in which order are the extra elements destroyed?

(Implementation choices are interesting if you can find two implementations which differ.)

(This was inspired by a comment from James Kanze.)

like image 507
MSalters Avatar asked Sep 09 '25 20:09

MSalters


1 Answers

Based on the January 2012 working draft

The January 2012 working draft contains the C++11 standard plus minor editorial changes.

Source, working draft

For vector:

void resize(size_type sz);
Effects: If sz <= size(), equivalent to erase(begin() + sz, end());. If size() < sz, appends sz - size() value-initialized elements to the sequence.

vector::erase does not specify the order of removal. I would expect it to be in order from begin() + sz to end(), because that makes sense to me, but that is just my expectation. I can't find anything about it in the standard.

The implementation of vector distributed with Visual Studio 2013 does appear to indeed erase in that order, as does MinGW's g++ 4.8.1 as well as g++ 4.7.3 (not MinGW). These are the compilers I happen to have easy access to.

In the same standard, for list:

void resize(size_type sz);
1 Effects: If size() < sz, appends sz - size() value-initialized elements to the sequence. If sz <= size(), equivalent to

list<T>::iterator it = begin();
advance(it, sz);
erase(it, end());

and

void resize(size_type sz, const T& c);
Effects:

if (sz > size())
    insert(end(), sz-size(), c);
else if (sz < size()) {
    iterator i = begin();
    advance(i, sz);
    erase(i, end());
}
else
    ; // do nothing

It then goes on to specify absolutely nothing useful about ordering for list::erase.

The implementation of list distributed with Visual Studio 2013 does appear to erase in reverse order, while MinGW's g++ 4.8.1 and g++ 4.7.3 (not MinGW) do not.

Based on the latest working draft at the time of writing

Working draft

For vector

void resize(size_type sz);
Effects: If sz <= size(), equivalent to calling pop_back() size() - sz times. If size() < sz, appends sz - size() default-inserted elements to the sequence.

This indicates that elements are removed in reverse order.

For list:

void resize(size_type sz);
1 Effects: If size() < sz, appends sz - size() value-initialized elements to the sequence. If sz <= size(), equivalent to

list<T>::iterator it = begin();
advance(it, sz);
erase(it, end());

and

void resize(size_type sz, const T& c);
Effects:

if (sz > size())
    insert(end(), sz-size(), c);
else if (sz < size()) {
    iterator i = begin();
    advance(i, sz);
    erase(i, end());
}
else
    ; // do nothing

It then goes on to specify absolutely nothing useful about ordering for list::erase.

For deque the standard specifies the same behavior as for vector.

like image 167
Bart van Nierop Avatar answered Sep 13 '25 11:09

Bart van Nierop