Re: avoiding temporaries
Marek Vondrak wrote:
class Vector
{
public:
// ...
Vector operator=( const Vector & v )
{
this->~Vector();
new( this ) Vector( v ); // [1]
}
private:
int data[ 20 ];
};
void test( Vector & a, const Vector & b, const Vector & c )
{
a = b + c; // [2]
}
[1]: Vector::operator=( const Vector & v ) deletes the existing Vector
instance and copy-constructs "v" in the old storage. Is this legal?
Legal in itself but not recommended in general. What would happen if:
(1) allocation or construction threw an exception, or
(2) an object is assigned to itself (v = v)?
You have already destroyed the object, so there's no way to recover.
You may think 'v = v' in (2) is silly, but the left- and the right-hand
sides can have different names which refer to the same object; e.g.
void foo(Vector& a, Vector& b)
{
/* ...*/
a = b; // seems completely innocuous
/* ... */
}
Vector x;
foo(x, x);
Therefore, the general idiom for assignment is to construct a new
copy of the right-hand side, and swap it with the left-hand side,
where the swapping preferably takes constant time and is guaranteed
not to throw any exception.
In this case, int[20] cannot be swapped in constant time, unfortunately.
Vector<int> can be, but they require dynamic allocation, so you cannot
have the best of both.
Has anyone considered proposing a "replacement constructor" that could
be invoked in place of operator=() under certain cirmustances which would
together with NRVO solve this problem and avoided the temporary in the first
place?
The temporary is IMHO not the problem, but it's the wasteful copying of
the temporary and throwing it away. With the 'move' or the 'rvalue
reference' proposal, the assignment operator could take the temporary
and move its contents to the destination without having to copy, so it
would solve the problem.
But I guess your Vector class has to copy the array data member anyway
because an array cannot be moved efficiently, while a pointer (to an
array, or to the initial element of the array) can.
NRVO means, IIRC, that the compiler directly constructs the destination
variable with the result, so with NRVO there is no temporary involved in
cases as
Vector a = b + c;
but I'm not sure it will be helpful in your case where the destination
is not constructed on the fly but should be assigned to.
Vector& a = /* ... */;
a = b + c;
It's assignment, not construction, that should happen here, and you need
the 'move' or the 'rvalue reference' to avoid copying the temporary.
Please correct me if I'm wrong.
--
Seungbeom Kim
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]