Boost logo

Boost Users :

From: Jonathan Brownell (alphaomega_at_[hidden])
Date: 2002-01-16 15:44:20


I have a question for all you C++ gurus. I'm writing a class that I
would like to use the following technique in, and I'm not sure if it's
portable or even legal, although VC++6 and VC++.NET, which I'm compiling
in, work beautifully with it.

Consider the following class, a very simplified example that I wrote to
demonstrate:

class House
{
public:
        explicit House(const int rooms) : m_rooms(rooms) { }
        ~House() { }

private:
        const int m_rooms;
};

Pretty straightforward. I'd like m_rooms to remain const to protect it
from accidental modification by member functions, since it will *never*
be changed during operation.

Now, the first problem that arises is that this is illegal: House
housingComplex[100]; Because, obviously, the constructor requires that
the number of rooms be passed to it. (Yes, we could create it as an
array of House pointers and create them dynamically, but in my case that
will require inconveniences by everybody using my class.) So, we make it
a default parameter and add an assignment operator:

class House
{
public:
        explicit House(const int rooms = -1) : m_rooms(rooms) { }

        ~House() { }

        House& operator =(const House& source);

private:
        const int m_rooms;
};

When rooms == -1, the House is considered to be uninitialized. Now, we
can do the following:

House housingComplex[100];
housingComplex[0] = House(5);
housingComplex[1] = House(4);
(etc)

The question is, how to implement the assignment operator? This is my
method:

House& House::operator =(const House& source)
{
        assert(m_rooms == -1);
        this->~House();
        new(this) House(source);
        return *this;
}

Yikes! I know this looks weird. First, assert verifies in debug mode
that the object is in its uninitialized state. Then, the destructor is
called manually to destruct the class and its contents. (In the actual
class I'm working on, there are numerous member variables that must be
appropriately destructed, and all of them are - I've checked.) Simply
calling ~House(); will not compile, because the compiler assumes I'm
trying to use the ~ operator illegally, so I have to call it through the
'this' pointer.

Then, the placement new operator is used to create a new House in
exactly the same space in memory as the old one, using the default copy
constructor so that all the const variables are (re)initialized.
Finally, a technicality for all assignment operators, a reference to the
object is returned. (This is so C-style expressions like "var1 = var2 =
var3 = 5;" can be used.)

Now, this works beautifully on my VC++. But... is it legal C++?? Am I
entering the realm of "undefined behavior", or is this a perfectly
legitimate technique? Is there an obviously better solution to my
problem? Are there caveats that I should be looking out for? Please,
someone with more knowledge of the C++ standards, give me a hand here.

Thanks!

-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