Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't constructors be explicitly called while destructors can?

In the following C++ code, I am allowed to explicitly call the destructor but not the constructor. Why is that? Wouldn't be explicit ctor call more expressive and unified with the dtor case?

class X { };

int main() {
  X* x = (X*)::operator new(sizeof(X));
  new (x) X;  // option #1: OK
  x->X();     // option #2: ERROR

  x->~X();
  ::operator delete(x);
}
like image 997
Daniel Langr Avatar asked Jul 17 '17 10:07

Daniel Langr


People also ask

Can you call a destructor in a constructor?

When you throw from the constructor, it will call the destructor of any object constructed so far: the member variables and the inherited classes (section 15.2/2). If you call the destructor manually, their destructor will be also called (section 12.4/8).

How do you call a constructor explicitly in C++?

Explicit Constructor Chaining using this() or super() To call a non-default superclass constructor from a subclass, use the super() keyword. For instance, if the superclass has multiple constructors, a subclass may always want to call a specific constructor, rather than the default.

Is constructor can be manually called whenever required?

No, you cannot call a constructor from a method. The only place from which you can invoke constructors using “this()” or, “super()” is the first line of another constructor.

How the constructors and destructors can be?

Like other member functions, constructors and destructors are declared within a class declaration. They can be defined inline or external to the class declaration. Constructors can have default arguments. Unlike other member functions, constructors can have member initialization lists.


2 Answers

Because before the constructor is started, there is no object of type X at that address. As such, dereferencing x as an X type or accessing members/methods of it would be Undefined Behavior.

So the major difference between x->X(); (hypothetical syntax) and x->~X() is that in the 2nd case you have an object on which you can call a (special) member such as the destructor, while in the first case, there is no object yet on which you can call methods (even the special method - constructor).

You could argue that there could be an exception to this rule, but then it ultimately would be a matter of syntax preference, where you have inconsistencies in both cases. With the current syntax the call to constructor doesn't look like a call to constructor, in your proposed syntax there would be symmetry with the destructor call, but inconsistencies in the rules which govern when you can dereference/access methods of an object. Actually there would have to be an exception allowing calling a method on something that is not a object yet. Then you would have to strictly define in the letter of the standard something that is not an object yet.

like image 158
bolov Avatar answered Oct 20 '22 12:10

bolov


This is a variation of the chicken-and-egg problem.

You can call destructors explicitly, as if they were member functions, because the instance of the object already exists.

You cannot do the same to a constructor, because an instance on which you would call it needs to exist, and be fully initialized by a constructor.

The only exception to this is when you have allocated memory for the object, but have not yet initialized the instance (i.e. the memory for the instance is there, but it has not been initialized to become an actual instance). Hence, you need to call a constructor. This is the situation when placement new, the syntax you show under "option 1" comment, is useful. However, this is not a member call that you perform on an instance, because the instance is not available prior to making that call.

like image 9
Sergey Kalinichenko Avatar answered Oct 20 '22 12:10

Sergey Kalinichenko