Boost logo

Boost Users :

From: Jonathan Brownell (alphaomega_at_[hidden])
Date: 2002-01-17 11:31:29


> > House& House::operator =(const House& source)
> > {
> > assert(m_rooms == -1);
> > this->~House();
> > new(this) House(source);
> > return *this;
> > }
> It is not exception safe: If the copy constructor
> fails due to an exception, then the "this" object will
> be left in a destroyed state. It will probably be
> destroyed again when your object leaves scope.
> Destroying an object twice is undefined behavior.

Good point.

> If you derive off of your "house" object, then this
> assignment operator will slice any of the derived
> parts...

Assignment operators aren't inherited, though, so if I derive a new
class, say, Mansion, this would be illegal rather than slice off derived
parts:
Mansion x, y;
x = y;

Mansion would have to define its own assignment operator, if needed. (A
client could hypothetically cast a Mansion to a House& and use its
assignment operator, but no right-minded C++ programmer should resort to
something that flagrant, and it would fail rather obviously if the
object is used afterwards.)

> In general, assignment operator should look like this
> (WARNING: untested code)
> House& House::operator =(const House& source)
> {
> House temp(source);
> Swap(temp);
> return *this;
> }
>
> The Swap() function is a member function that has
> "No-Throw" specification. It swaps out the internals
> of the *this instance with the "temp" instance.

This makes sense, and would work for nearly all other types of classes.
But, is there any way to implement Swap so that it can swap out const
data members? I certainly can't do something like:

House* temp = new House(source);
memcpy(this, temp, sizeof(House);

// don't call original destructor
delete static_cast<void*>(temp);

(I should be horsewhipped for even *thinking* of such dangerous
implementations, don't you think?)

Essentially what I need is a const data member that is protected as a
const except during House::operator =(const House&), at which point the
entire class is replaced. Am I just out of luck? If so, this makes const
class data members pretty useless in many cases, because similar
situations to this have arisen quite a few times for me.

> Using this method, you are still writing your
> assignment operator in terms of your copy constructor,
> so you don't need to duplicate work. And this method
> is strongly exception safe; if the copy constructor
> throws, then the current object is unchanged.
>
> Also, I would recommend that you either reconsider
> having the constant member variable, or use a
> vector<>.

Using a vector<T> won't work in this case, because the STL uses
T::operator = in order to copy vector contents into new locations during
memory reallocation. And there's no logical way to implement operator =
when a const data member is present, which is the cause of this
conversation.
I could use std::list, since it doesn't do reallocation, but clients
using this class in containers will most likely need random access
iterators.

Any other ideas?

-Jonathan


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net