|
Boost : |
From: Joe Gottman (jgottman_at_[hidden])
Date: 2005-02-14 20:35:31
I just discovered that optional<T> is not safe under self-assignment.
Consider the following code fragment:
boost::optional<long> x(1); //At this point x is initialized and *x == 1
x = x; //x should be unchanged, but instead x is now uninitialized
Optional's assignment operator looks like
optional& operator= ( optional const& rhs )
{
this->assign( rhs ) ;
return *this ;
}
and assign is defined by
void assign ( argument_type val )
{
destroy();
construct(val);
}
Thus, if (this == &rhs) in operator=(), any value held by rhs will be
destroyed.
I can see two possible fixes for this. the first is to put an "if (this !=
&rhs) " around the call to assign in operator=(). This is simplest, but it
slows the code down in order to protect against a very rare situation. The
other is to rewrite assign as follows:
void assign(argument_type val)
{
if (m_initialized) {
get() = val; // call assignment operator
} else {
construct(val); //call copy constructor
}
return *this;
}
This makes optional self-assignment safe. It has the added advantage that
is T's assignment operator has the strong exception safety guarantee, so
does optional<T>'s assignment operator. It has the disadvantage of making
optional depend on both assignment operator and copy constructor to copy,
but very few classes have a copy constructor but don't have an assignment
operator.
Joe Gottman
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk