Why can swapping standard library containers be problematic in C++11 (involving allocators)?

前端 未结 1 419
余生分开走
余生分开走 2020-12-29 10:24

Note: Originially asked by GreenScape as comment.


After reading Why are the swap member functions in STL containers not declared no

相关标签:
1条回答
  • 2020-12-29 10:48

    Let's start of by digging into the Standard (N3797):

    23.2.1p9 General Container Requirements [container.requirements.general]

    If allocator_traits<allocator_type>::propagate_on_container_swap::value is true, then the allocators of a and b shall also be exchanged using an unqalified call to non-member swap. Otherwise, they shall not be swapped, and the behavior is undefined unless a.get_allocator() == b.get_allocator().


    What is the purpose of propagate_on_container_swap?

    If an Allocator has a typedef named propagate_on_container_swap that refers to std::true_type the underlying Allocators of two containers being swapped, will also swap.[1]

    If propagate_on_container_swap is std::false_type only the data of the two containers will swap, but the allocators will remain in their place.

    [1] This means that after a.swap(b), a.get_allocator() will be that which was previously b.get_allocator(); the allocators has swapped.


    What are the implications of stateful Allocators?

    The Allocator is not only responsible for allocating memory for the elements within a Standard container, they are also responsible for the deallocation of said elements.

    C++03 didn't allow stateful allocators within standard containers, but C++11 mandates that support for such must be present. This means that we could define an allocator that, depending on how it's constructed, acts in a certain way.

    If the allocator has propagate_on_container_swap::value equal to false the difference in state between the two allocators involved might lead to undefined behavior, since one instance of the Allocator might not be compatible with the data handled by the other.


    What might be the problem with stateful allocators if they are not swapped properly?

    Let's say we have a MagicAllocator which either uses malloc or operator new to allocate memory, depending on how it's constructed.

    If it uses malloc to allocate memory it must use free to deallocate it, and in case of operator new, delete is required; because of this it must maintain some information saying which of the two it should use.

    If we have two std::vector which both uses MagicAllocator but with different states (meaning that one uses malloc and the other operator new), and we don't swap the allocators upon a.swap(b) the allocator won't match the memory allocated for the elements in the two vectors after the swap - which in terms means that the wrong free/delete might be called upon deallocation.

    0 讨论(0)
提交回复
热议问题