UPDATE at the bottom
q1: How would you implement the rule of five for a class that manages rather heavy resources, but of which you
If your object is resource-heavy, you might want to avoid copying altogether, and just provide the move constructor and move assignment operator. However, if you really want copying too, it is easy to provide all of the operations.
Your copy operations look sensible, but your move operations don't. Firstly, though an rvalue reference parameter will bind to an rvalue, within the function it is an lvalue, so your move constructor ought to be:
AnObject( AnObject&& rh ) :
n( std::move(rh.n) ),
a( std::move(rh.a) )
{
rh.n = 0;
rh.a = nullptr;
}
Of course, for fundamental types like you've got here it doesn't actually make a difference, but it's as well to get in the habit.
If you provide a move-constructor, then you don't need a move-assignment operator when you define copy-assignment like you have --- because you accept the parameter by value, an rvalue will be moved into the parameter rather than copied.
As you found, you can't use std::swap() on the whole object inside a move-assignment operator, since that will recurse back into the move-assignment operator. The point of the comment in the post you linked to is that you don't need to implement a custom swap if you provide move operations, as std::swap will use your move operations. Unfortunately, if you don't define a separate move assignment operator this doesn't work, and will still recurse. You can of course use std::swap to swap the members:
AnObject& operator=(AnObject other)
{
std::swap(n,other.n);
std::swap(a,other.a);
return *this;
}
Your final class is thus:
class AnObject
{
public:
AnObject( size_t n = 0 ) :
n( n ),
a( new int[ n ] )
{}
AnObject( const AnObject& rh ) :
n( rh.n ),
a( new int[ rh.n ] )
{
std::copy( rh.a, rh.a + n, a );
}
AnObject( AnObject&& rh ) :
n( std::move(rh.n) ),
a( std::move(rh.a) )
{
rh.n = 0;
rh.a = nullptr;
}
AnObject& operator = ( AnObject rh )
{
std::swap(n,rh.n);
std::swap(a,rh.a);
return *this;
}
~AnObject()
{
delete [] a;
}
private:
size_t n;
int* a;
};