Possible Duplicate:
Move semantics == custom swap function obsolete?
This is how std::swap
looks like in C++11:
template<typename T>
void swap(T& x, T& y)
{
T z = std::move(x);
x = std::move(y);
y = std::move(z);
}
Do I still have to specialize std::swap
for my own types, or will std::swap
be as efficient as it gets, provided that my class defines a move constructor and a move assignment operator, of course?
The specialization of std::swap
is now optional, but not deprecated. The rationale is performance.
For prototyping code, and perhaps even for much shipping code, std::swap
will be plenty fast. However if you're in a situation where you need to eek out every little bit from your code, writing a custom swap can still be a significant performance advantage.
Consider the case where your class essentially has one owning pointer and your move constructor and move assignment just have to deal with that one pointer. Count machine loads and stores for each member:
Move constructor: 1 load and 2 stores.
Move assignment: 2 loads and 2 stores.
Custom swap: 2 loads and 2 stores.
std::swap
is 1 move construction and 2 move assignments, or: 5 loads and 6 stores.
A custom swap is potentially still two or three times faster than std::swap
. Though any time you're trying to figure out the speed of something by counting loads and stores, both are going to be wicked fast.
Note: In computing the cost of your move assignment, be sure and take into account that you will be moving into a moved-from value (in the std::swap
algorithm). This often negates the cost of a deallocation, though at the cost of a branch.
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. My preference is to combine copy-and-swap idiom with customizing std::swap
for my classes.
That means I will have:
class Aaaa
{
public:
Aaaa(); // not interesting; defined elsewhere
Aaaa(Aaaa&& rvalueRef); // same
Aaaa(const Aaaa& ref); // same
~Aaaa(); // same
Aaaa& operator=(Aaaa object) // copy&swap
{
swap(object);
return *this;
}
void swap(Aaaa& other)
{
std::swap(dataMember1, other.dataMember1);
std::swap(dataMember2, other.dataMember2);
// ...
}
// ...
};
namespace std
{
template<> inline void std::swap(Aaaa& left, Aaaa& right)
{ left.swap(right); }
}
That will depend on your Types.
You will move it from x to z, from y to x, from z to y. That is three copy operations of the underlying representation (maybe only one pointer, maybe something more, who knows)
Now maybe you can create a faster swap for your type (xor swap trick, inline assembler, or maybe std::swap for your underlying types is just faster).
Or maybe also your compiler is good at optimizing, and essentially optimizes both cases into the same instructions (like have the temporary in a register).
I personally tend to always implement a swap member function that will be called from several places, including things like move assignment, but YMMV.
This swap()
calls a move constructor and 2 move assignments. I think one can write more efficient swap()
for his particular type of class like,
class X
{
int * ptr_to_huge_array;
public:
// ctors, assgn ops. etc. etc.
friend void swap(X& a, X& b)
{
using std::swap;
swap(a.ptr_to_huge_array, b.ptr_to_huge_array);
}
};
regardless of the implementation of move constructor and assignment operator.