Search code examples
c++c++11swapmove-semanticsobsolete

Move semantics == custom swap function obsolete?


Recently, many questions pop up on how to provide your own swap function. With C++11, std::swap will use std::move and move semantics to swap the given values as fast as possible. This, of course, only works if you provide a move constructor and a move assignment operator (or one that uses pass-by-value).

Now, with that given, is it actually necessary to write your own swap functions in C++11? I could only think of non-movable types, but then again, the custom swaps usually work through some kind of "pointer exchange" (aka moving). Maybe with certain reference variables? Hm...


Solution

  • It is a matter of judgment. I will typically let std::swap do the job for prototyping code, but for release code write a custom swap. I can usually write a custom swap that is about twice as fast as 1 move construction + 2 move assignments + 1 resourceless destruction. However one may want to wait until std::swap actually proves to be a performance problem before going to the bother.

    Update for Alf P. Steinbach:

    20.2.2 [utility.swap] specifies that std::swap(T&, T&) has a noexcept equivalent to:

    template <class T>
    void
    swap(T& a, T& b) noexcept
                     (
                        is_nothrow_move_constructible<T>::value &&
                        is_nothrow_move_assignable<T>::value
                     );
    

    I.e. if move operations on T are noexcept, then std::swap on T is noexcept.

    Note that this spec doesn't require move members. It only requires that construction and assignment from rvalues exists, and if it is noexcept, then swap will be noexcept. E.g.:

    class A
    {
    public:
        A(const A&) noexcept;
        A& operator=(const A&) noexcept;
    };
    

    std::swap<A> is noexcept, even without move members.