I refer to this question: What is the copy-and-swap idiom?
Effectively, the above answer leads to the following implementation:
class MyClass
{
public:
friend void swap(MyClass & lhs, MyClass & rhs) noexcept;
MyClass() { /* to implement */ };
virtual ~MyClass() { /* to implement */ };
MyClass(const MyClass & rhs) { /* to implement */ }
MyClass(MyClass && rhs) : MyClass() { swap(*this, rhs); }
MyClass & operator=(MyClass rhs) { swap(*this, rhs); return *this; }
};
void swap( MyClass & lhs, MyClass & rhs )
{
using std::swap;
/* to implement */
//swap(rhs.x, lhs.x);
}
However, notice that we could eschew the swap() altogether, doing the following:
class MyClass
{
public:
MyClass() { /* to implement */ };
virtual ~MyClass() { /* to implement */ };
MyClass(const MyClass & rhs) { /* to implement */ }
MyClass(MyClass && rhs) : MyClass() { *this = std::forward<MyClass>(rhs); }
MyClass & operator=(MyClass rhs)
{
/* put swap code here */
using std::swap;
/* to implement */
//swap(rhs.x, lhs.x);
// :::
return *this;
}
};
Note that this means that we will no longer have a valid argument dependent lookup on std::swap with MyClass.
In short is there any advantage of having the swap() method.
edit:
I realized there is a terrible mistake in the second implementation above, and its quite a big thing so I will leave it as-is to instruct anybody who comes across this.
if operator = is defined as
MyClass2 & operator=(MyClass2 rhs)
Then whenever rhs is a r-value, the move constructor will be called. However, this means that when using:
MyClass2(MyClass2 && rhs)
{
//*this = std::move(rhs);
}
Notice you end up with a recursive call to the move constructor, as operator= calls the move constructor...
This is very subtle and hard to spot until you get a runtime stack overflow.
Now the fix to that would be to have both
MyClass2 & operator=(const MyClass2 &rhs)
MyClass2 & operator=(MyClass2 && rhs)
this allows us to define the copy constructors as
MyClass2(const MyClass2 & rhs)
{
operator=( rhs );
}
MyClass2(MyClass2 && rhs)
{
operator=( std::move(rhs) );
}
Notice that you write the same amount of code, the copy constructors come "for-free" and you just write operator=(&) instead of the copy constructor and operator=(&&) instead of the swap() method.