Search code examples
c++operator-overloadingplacement-new

Can I use placement new(this) in operator=?


Background: I have a complicated class with many variables. I have a sound and tested copy constructor:

Applepie::Applepie( const Applepie &copy) :
m_crust(copy.m_crust),
m_filling(copy.m_filling)
{
}

Some of the member variable copy constructors called in the intializer list perform allocation.

Question: I need to create operator=. Rather than duplicating the existing constuctor with assignment instead of initialization list, and freeing memory that's being replaced, and etc etc etc, can I simply do the following:

Applepie& Applepie::operator=( const Applepie &copy)
{
    if( this != &copy)
    {
       this->~Applepie(); // release own object
       new(this) Applepie(copy); // placement new copy constructor
    }
    return *this;
}

In other words, is destroy self followed by a placement new copy constructor semantically identical to operator= ?

This seems to have the potential to dramatically reduce repeat code and confirming that each variable is initialized properly, at the cost of potential slight loss of efficiency during assignment. Am I missing something more obscure?

Rationale: My actual class has about 30 varaibles. I am concerned about the fact that both my copy constructor and my assignment operator have to copy all thirty, and that the code might diverge, causing the two operations to do things differently.


Solution

  • As Herb Sutter in "Exceptional C++" states, it is not exception safe. That means, if anything is going wrong during new or construction of the new object, the left hand operand of the assignment is in bad (undefined) state, calling for more trouble. I would strongly recommend using the copy & swap idiom.

    Applepie& Applepie::operator=(Applepie copy)
    {
      swap(m_crust, copy.m_crust);
      swap(m_filling, copy.m_filling);
      return *this;
    }
    

    When your object uses the Pimpl idiom (pointer to implementation) also, the swap is done by changing only two pointers.