Before C ++ 11 introduced the transfer semantics, the general implementation of std::swap had no choice but to make two copies. Conceptually, this is:
template <class T> void swap(T &a, T &b) { T t(a); a = b; b = t; }
Note that this generic std::swap does not know anything about the internals of the passed object (because it can be called with an arbitrary user type, for example) and therefore must make copies. Note that for containers, this means copying items.
Providing an optimized swap member function that simply reassigns some internal pointers is therefore a big performance benefit.
Since the semantics of displacement has been introduced, general exchange can be made more efficient using moves. Again, conceptually:
template <class T> void swap(T &a, T &b) { T t(::std::move(a)); a = ::std::move(b); b = ::std::move(t); }
Of course, in practice, he probably has requirements that the move operations include not throwing and all kinds of extra bits.
With the semantics of in-place movement, optimized versions of members are perhaps less important than before. But it is still possible that with knowledge of the exact details of the type implementation, their replacement can be faster than three general movements.
In addition to the discussion above, note that std::swap overloads exist for almost all types defined in the standard library. What these overloads do is simply invoke the optimized swap member function on one of the operands. Thus, you have the best of both worlds: a common free swap function that can be called with anything, but which optimized implementations for everything the standard library knows about.
It would be possible to abandon the member functions and provide optimized implementations inside the std::swap overloads directly, but this would mean that they probably should be friendly and might be perceived as less accessible for user code.
Angew
source share