Re: C++ FAQ Lite 12.3
* James Kanze:
On Feb 12, 3:03 pm, Victor Bazarov <v.Abaza...@comAcast.net> wrote:
Alf P. Steinbach wrote:
* stf:
http://www.parashift.com/c++-faq-lite/assignment-operators.html#faq-12.3
[...]
A generally better solution is the swap idiom, expressing
assignment in terms of construction instead of the other
way.
void Fred::swap( Fred& other ) throw()
{
std::swap( p_, other.p_ );
}
Fred& Fred::operator( Fred other )
Did you mean
operator=
? And I understand that 'swap' would need a modifiable
'other' but do you really think that making a copy (to pass by
value) is a good idea?
I think he just messed up in typing the example. His code isn't
the standard swap idiom. You can only swap modifiable objects.
This really should be:
Fred tmp( *other ) ;
swap( tmp ) ;
return *this ;
I think your first '*' is a typo.
And no, except for my typo (missing '=') I meant what I wrote, like
Fred& Fred::swap( Fred other ) { swap( other ); }
'other' is passed by value and is a modifiable object.
Alternatively 'other' can be passed by reference to const, and then a
declaration of a temporary is needed, but it's just more to write.
[snip]
However there are cases where the swap idiom isn't
necessesarily most natural or practical or efficient.
The code above assumes that swapping is essentially
cost-free, as it is when the real state is just a pointer to
something dynamically allocated.
It also assumes (the case here) that swap can't throw.
Yes, that's what the 'throw()' means.
That's a
very, very important criterion in order to use the swap idiom:
that you can provide a swap function that cannot throw. If your
object contains other objects which don't provide a no-throw
swap, you probably can't.
Perhaps you just missed the whole point... The issue is with
self-assignment. Essentially, the whole idiom of checking
against self-assignment is replaced in the FAQ case with
reallocation and actual assignment, hoping it doesn't happen
often. You simply wrap (hide) that into making a copy upon
calling the assignment operator, right? Wouldn't you have to
deal with the OP's 'throw' issue in the copy constructor,
then?
You missed an important part of the point. If you implement the
code something like:
if ( this != &other ) {
delete p_ ;
p_ = new Wilma( *other.p_ ) ;
}
, then there's no problem with self assignment. But if the
constructor of Wilma throws, you're going to have serious
problems when the destructor of the object (or any other member
function, for that matter) is called.
Alf's right in his analysis, and his explinations. He just got
screwed up in the example code (not enough coffee?).
:-)
Well, a missing '=' isn't all that much, I think.
Cheers,
- Alf