Is there something similar to the copy-and-swap idiom when allocators are involved?

后端 未结 1 1458
遥遥无期
遥遥无期 2021-02-04 14:26

There were a couple of great answers about the copy-and-swap idiom, e.g., explaining the copy and swap idiom and explaining move semantics. The basic idiom working for

相关标签:
1条回答
  • 2021-02-04 15:11

    You seem to imply that the classic copy/swap idiom does work for the case that all of the propagate_on_ traits are not false. I don't believe this is the case. For example consider:

    std::allocator_traits<A>::propagate_on_container_copy_assignment::value == true
    std::allocator_traits<A>::propagate_on_container_swap::value == false
    

    The classic copy/swap idiom assignment operator will not propagate the allocator from the rhs to the lhs, and will instead enter a state of undefined behavior if the two allocator states are not equal.

    Your rewrite for the copy assignment operator also does not work this this combination of propagate_on_ traits, because it never propagates the allocator on copy assignment.

    I do not believe the copy/swap idiom is advised if one wants to follow the rules for std::containers.

    I keep an "allocator behavior" cheat sheet for myself that describes how these members should behave (in English as opposed to standard-eze).

    copy assignment operator

    If propagate_on_container_copy_assignment::value is true, copy assigns the allocators. In this case, if allocators are not equal prior to the assignment, then first deallocates all memory on the lhs. Then proceeds with copy assigning the values, without transferring any memory ownership. I.e. this->assign(rhs.begin(), rhs.end()).

    move assignment operator

    1. If propagate_on_container_move_assignment::value is true, deallocate all memory on the lhs, move assign the allocators, then transfer memory ownership from the rhs to the lhs.

    2. If propagate_on_container_move_assignment::value is false, and the two allocators are equal, then deallocate all memory on the lhs, then transfer memory ownership from the rhs to the lhs.

    3. If propagate_on_container_move_assignment::value is false, and the two allocators are not equal, move assign as if this->assign(make_move_iterator(rhs.begin()), make_move_iterator(rhs.end()).

    These descriptions are intended to lead to the highest performance possible, while adhering to the C++11 rules for containers and allocators. Whenever possible, memory resources (such as vector capacity()) are either transferred from the rhs, or reused on the lhs.

    The copy/swap idiom always throws away memory resources (such as vector capacity()) on the lhs, instead preemptively allocating such resources in a temporary just prior to deallocating them on the lhs.

    For completeness:

    swap

    If propagate_on_container_swap::value is true, swaps allocators. Regardless, swaps memory ownership. The behavior is undefined if propagate_on_container_swap::value is false and the allocators are not equal.

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