The C++ syntax to explicitly invoke a constructor has a weird name and lives up to this name, because it's something that's very rarely done - usually only in library/foundation code. It's called placement new, and no, it has nothing to do with memory allocation - this is the weird syntax to invoke constructors explicitly in C++:
DerivedClass::DerivedClass() { new (this) BaseClass(); }
DerivedClass::DerivedClass() { new (this) BaseClass(42); }
So, in your question, this is what you meant to ask about, but didn't know :) I imagine that this weird syntax is helpful since if it were easy, then people coming from languages where such constructor calls are commonplace (e.g. Pascal/Delphi) could write lots of seemingly working code that would be totally broken in all sorts of ways. Undefined behavior is not a guarantee of a crash, that's the problem. Superficial/obvious UB often results in crashes (like null pointer access), but a whole lot of UB is a silent killer. So making it harder to write incorrect code by making some syntax obscure is a desirable trait in a language.
The "second option" in the question has nothing to do with constructor "calls". The C++ syntax of creating a default-constructed instance of a value of BaseClass
object is:
BaseClass();
{
BaseClass __temporary{};
}
In C++ the notion of a construction of an object instance is all-permeating: you do it all the time, since the language semantics equate the existence of an object with that object having been constructed. So you can also write:
// Constructs a temporary integer, and promptly destructs it.
int();
Objects of integer type are also constructed and destructed - but the constructor and destructor are trivial and thus there's no overhead.
Note that construction and destruction of an object this way doesn't imply any heap allocations. If the compiler decides that an instance has to be actually materialized (e.g. due to observable side effects of construction or destruction), the instance is a temporary object, just like the temporaries created during expression evaluation - a-ha, we notice that type()
is an expression!
So, in your case, that Person();
statement was a no-op. In code compiled in release mode, no machine instructions are generated for it, because there's no way to observe the effects of this statement (in the case of the particular Person
class), and thus if no one is there to hear the tree fall, then the tree doesn't need to exist in the first place. That's how C++ compilers optimize stuff: they do lot of work to prove (formally, in a mathematical sense) whether the effects of any piece of code may be unobservable, and if so the code is treated as dead code and removed.
placement new
(不确定是否可以这样做),或者有时可以通过实用程序函数调用来模拟。https://stackoverflow.com/questions/62434909/manually-calling-constructor-of-base-class-outside-initialization-list - oromoiluig