The standard does not seem to discuss reentrant access to a container during removal of an element, leaving it unclear whether a removed object is destroyed before or after it is removed from the container. For example, the behavior of the following code seems to be unspecified:
#include <iostream> #include <map> #include <memory> struct T; typedef std::map<int, std::shared_ptr<T>> TMap; struct T { T(TMap* t_map, int index) : t_map(t_map), index(index) {} ~T() { std::cout << "Object " << index << " is "; if (t_map->count(index)) std::cout << "destroyed before being removed from the map" << std::endl; else std::cout << "removed from the map before being destroyed" << std::endl; } static void AddToMap(TMap* map, int index) { (*map)[index] = std::make_shared<T>(map, index); } TMap* t_map; int index; }; int main() { TMap t_map; T::AddToMap(&t_map, 0); T::AddToMap(&t_map, 1); t_map.erase(1); t_map.erase(0); }
The output of this program in Visual Studio 2013 is:
Object 1 is removed from the map before being destroyed Object 0 is destroyed before being removed from the map
The core issue here is whether an object removed from a container should be destroyed before or after it is removed from the container. The current standard seems to be silent on this issue. The above output demonstrates that the behavior is actually inconsistent. (It's difficult to fully describe Visual Studio's behavior; for example, changing main() in the above example to the following:)
int main() { TMap t_map; T::AddToMap(&t_map, 0); T::AddToMap(&t_map, 1); T::AddToMap(&t_map, 2); T::AddToMap(&t_map, 3); t_map.erase(3); t_map.clear(); }
(...gives this output:)
Object 3 is removed from the map before being destroyed Object 2 is destroyed before being removed from the map Object 1 is destroyed before being removed from the map Object 0 is removed from the map before being destroyed
In my opinion, the standard should explicitly describe when objects are destroyed as part of removal from a container. To me, it makes the most sense to say that objects should be removed from the container before they are destroyed.