Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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...

like image 387
Xeo Avatar asked Jun 20 '11 19:06

Xeo


People also ask

Does STD swap use move semantics?

Is specializing std::swap deprecated now that we have move semantics? No. This is the generic version, but you can optimize it to skip a third move operation.

Does C++ have a swap function?

swap() function in C++ The swap() function is used to swap two numbers. By using this function, you do not need any third variable to swap two numbers. Here is the syntax of swap() in C++ language, void swap(int variable_name1, int variable_name2);

Is there a built in swap function in C?

To answer your question directly, no there is no swap function in standard C, although it would be trivial to write.

Is swap built in C++?

The function std::swap() is a built-in function in the C++ Standard Template Library (STL) which swaps the value of two variables.


3 Answers

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.

like image 147
Howard Hinnant Avatar answered Oct 07 '22 18:10

Howard Hinnant


Sure, you can implement swap as

template <class T>
void swap(T& x, T& y)
{
  T temp = std::move(x);
  x = std::move(y);
  y = std::move(temp);
}

But we might have our own class, say A, which we can swap more quickly.

void swap(A& x, A& y)
{
  using std::swap;
  swap(x.ptr, y.ptr);
}

Which, instead of having to run a constructor and destructor, just swaps the pointers (which may well be implemented as XCHG or something similar).

Of course, the compiler might optimize out the constructor/destructor calls in the first example, but if they have side effects (i.e. calls to new/delete) it may not be smart enough to optimize them away.

like image 27
Clinton Avatar answered Oct 07 '22 18:10

Clinton


There might be some types that can be swapped but not moved. I don't know of any non-movable types, so I don't have any examples.

like image 22
Puppy Avatar answered Oct 07 '22 19:10

Puppy