You’ve missed a significant optimization in your copy assignment operator. And subsequently the situation has gotten confused.
AnObject& operator = ( const AnObject& rh )
{
if (this != &rh)
{
if (n != rh.n)
{
delete [] a;
n = 0;
a = new int [ rh.n ];
n = rh.n;
}
std::copy(rh.a, rh.a+n, a);
}
return *this;
}
Unless you really never think you’ll be assigning AnObject
s of the same size, this is much better. Never throw away resources if you can recycle them.
Some might complain that the AnObject
‘s copy assignment operator now has only basic exception safety instead of strong exception safety. However consider this:
Your clients can always take a fast
assignment operator and give it strong
exception safety. But they can’t take
a slow assignment operator and make it
faster.template <class T> T& strong_assign(T& x, T y) { swap(x, y); return x; }
Your move constructor is fine, but your move assignment operator has a memory leak. It should be:
AnObject& operator = ( AnObject&& rh )
{
delete [] a;
n = rh.n;
a = rh.a;
rh.n = 0;
rh.a = nullptr;
return *this;
}
…
Data a = MakeData(); Data c = 5 * a + ( 1 + MakeMoreData() ) / 3;
q2: Using a combination of copy elision / RVO / move semantics the
compiler should be able to this this
with a minimum of copying, no?
You may need to overload your operators to take advantage of resources in rvalues:
Data operator+(Data&& x, const Data& y)
{
// recycle resources in x!
x += y;
return std::move(x);
}
Ultimately resources ought to be created exactly once for each Data
you care about. There should be no needless new/delete
just for the purpose of moving things around.