Move semantics == custom swap function obsolete?
Solution 1:
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.
Solution 2:
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.