Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Caveats and risks of calling a constructor and destructor like common methods?

There's a point in my program where the state of a certain object needs to be reset "to factory defaults". The task boils down to doing everything that is written in the destructor and constructor. I could delete and recreate the object - but can I instead just call the destructor and the constructor as normal objects? (in particular, I don't want to redistribute the updated pointer to the new instance as it lingers in copies in other places of the program).

  MyClass {
  public:
        MyClass();
        ~MyClass();

  ...      
  }


  void reinit(MyClass* instance)
  {
        instance->~MyClass();
        instance->MyClass();
  }

Can I do this? If so, are there any risks, caveats, things I need to remember?

like image 237
SF. Avatar asked Feb 10 '23 01:02

SF.


2 Answers

If your assignment operator and constructor are written correctly, you should be able to implement this as:

void reinit(MyClass* instance)
{
    *instance = MyClass();
}

If your assignment operator and constructor are not written correctly, fix them.

The caveat of implementing the re-initialisation as destruction followed by construction is that if the constructor fails and throws an exception, the object will be destructed twice without being constructed again between the first and second destruction (once by your manual destruction, and once by the automatic destruction that occurs when its owner goes out of scope). This has undefined behaviour.

like image 93
Mankarse Avatar answered Apr 27 '23 02:04

Mankarse


You could use placement-new:

void reinit(MyClass* instance)
{
    instance->~MyClass();
    new(instance) MyClass();
}

All pointers remain valid.

Or as a member function:

void MyClass::reinit()
{
    ~MyClass();
    new(this) MyClass();
}

This should be used carefully, see http://www.gotw.ca/gotw/023.htm, which is about implementing an assignement operator with this trick, but some points apply here too:

  • The constructor should not throw
  • MyClass should not be used as a base class
  • It interferes with RAII, (but this could be wanted)

Credit to Fred Larson.

like image 33
alain Avatar answered Apr 27 '23 03:04

alain