Using new (this) to reuse constructors

Brandon Bodnar picture Brandon Bodnar · Mar 22, 2010 · Viewed 10.7k times · Source

This came up recently in a class for which I am a teaching assistant. We were teaching the students how to do copy constructors in c++, and the students who were originally taught java asked if you can call one constructor from another. I know the answer to this is no, as they are using the pedantic flag for their code in class, and the old standards do not have support for this. I found on Stackoverflow and other sites a suggestion to fake this using new (this) such as follows

class MyClass
{
    private:
        int * storedValue;
    public:
        MyClass(int initialValue = 0)
        {
            storedValue = new int(initialValue);
        }

        ~ MyClass()
        {
            delete storedValue;
        }

        MyClass(const MyClass &b)
        {
            new (this) MyClass(*(b.storedValue));
        }

        int value() {
            return *storedValue;
        }
};

This is really simple code, and obviously does not save any code by reusing the constructor, but it is just for example.

My question is if this is even standard compliant, and if there are any edge cases that should be considered that would prevent this from being sound code?

Edit: I should note that this seems very dangerous to me, but that is more from a view point of I don't really understand it more than knowing how it can go bad. I just wanted to make sure that if asked about it by students that I can direct them towards why the can or shouldn't do it. I already suggested to them for all practical purposes to use a shared initialization method. This is more of a teaching question than for a practical project.

Answer

tony picture tony · Mar 22, 2010

C++0x will introduce syntax to allow constructors to call other constructors.

Until then, new(this) works in some cases, but not all. In particular, once in the constructor, your base class(es) are already fully constructed. Reconstructing via new(this) re-calls the base constructors without calling the base destructors, so expect problems if the base classes weren't expecting this kind of hackery - and they probably weren't.

An example for clarity:

class Base
{
public:
   char *ptr;
   MyFile file;
   std::vector vect;
   Base()
   {
       ptr = new char[1000];
       file.open("some_file");
   }
   ~Base()
   {
       delete [] ptr;
       file.close();
   }
};

class Derived : Base
{
    Derived(Foo foo)
    {
    }
    Derived(Bar bar)
    {
       printf(ptr...);  // ptr in base is already valid
       new (this) Derived(bar.foo); // ptr re-allocated, original not deleted
       //Base.file opened twice, not closed
       // vect is who-knows-what
       // etc
    }
}

or as they say 'hilarity ensues'