std::vector::erase(iterator position) does not necessarily invoke the corresponding element's destructor

c++, stl

Solution

The C++11 standard 23.3.6.5/4 says (emphasis is mine):

Complexity: The destructor of T is called the number of times equal to the number of the elements erased, but the move assignment operator of T is called the number of times equal to the number of elements in the vector after the erased elements.

Had the implementation called the destructor on the 3rd element, it wouldn't be conform.

Indeed, suppose that the destructor is called on the 3rd element. Since only one element is erased, the desctructor cannot be called again.

After the destructor call, the 3rd position contains raw memory (not a fully constructd object `T`). Hence the implementation needs to call the move constructor to move from the 4th position to the 3rd one.

It cannot destroy the 4th element (because it can no longer call the destructor) and then to move from the 5th to the 4th element it must call the move assignment operator.

At this point, the implementation still needs to decrease the `vector` size by 1 and destroy the 5th element but, as we have seen, no other destrucor call is allowed. (Notice also that the move assignement operator would not be called twice as required by the standard.) QED.

Problem

Assuming I have a `std::vector` `V` of 5 elements, `V.erase(V.begin() + 2)` remove the 3rd element. STL `vector` implementation will move 4th and 5th element up, and then destruct the 5th element. I.e. erasing element i in a `vector` does not guarantee that ith destructor is called. For `std::list`, this is not the case. Erasing ith element invokes ith element's destructor. What does STL say about this behavior? This is code taken from my system's stl_vector.h: ``` 392 iterator erase(iterator __position) { 393 if (__position + 1 != end()) 394 copy(__position + 1, _M_finish, __position); 395 --_M_finish; 396 destroy(_M_finish); 397 return __position; ```

Original source