sharptooth
sharptooth

Reputation: 170499

What is the full list of actions performed by placement new in C++?

In this question creating a factory method when the compiler doesn't support new and placement new is discussed. Obviously some suitable solution could be crafted using malloc() if all necessary steps done by placement new are reproduced in some way.

What does placement new do - I'll try to list and hope not to miss anything - except the following?

What other actions are there?

Upvotes: 7

Views: 1202

Answers (3)

eel76
eel76

Reputation: 117

@laalto answer holds true in general. However, one exception proves the rule.

vtable pointers are initialized as part of constructor calls, not separately.

The Microsoft C++ compiler knows so-called local vftables, i.e. vftables are local to a DLL and will be cloned for every imported class. This is because the compiler wants to provide a modified destructor which wraps the original one (s.a. here).

Whenever you construct an object of an imported class the compiler generates code which overwrites the original vftable pointer(s) with local pointer(s) after constructor invocation. This code is also present in placement new calls.

There exists another workaround besides those mentioned in the post above. This workaround does not force you to alter the original header files. Please have a look here: https://godbolt.org/g/YQsffY

Upvotes: 0

Steve Jessop
Steve Jessop

Reputation: 279255

set vtable pointer accordingly

This part is almost completely implementation-defined. Your compiler might not use vtables. There may be multiple vtable pointers, or one or more pointers to things which are not vtables. Multiple inheritance is always entertaining, as are virtual base classes. This metadata is not guaranteed to be copyable with memcpy to another object, so the pointer(s) needn't be absolute. There could be offsets in there which are relative to the object pointer itself.

IIRC what commonly happens is that the base class constructor is called, then the vtable pointer is set to the base class, then the first derived class constructor is called, etc. This is in order to satisfy the requirements in the specification concerning what happens when a virtual function is called in a constructor. As far as I remember, there is no "list of actions" in the standard, just a defined initialisation order.

So it is not possible to generalise what an implementation does, especially since what you have is not an implementation of the C++ standard. If it cuts corners by leaving out "new", presumably with good reason because it thinks you shouldn't be using it on the target platform, then who knows what other rules of the language it ignores. If it were possible to mock up "new" with a malloc and a bit of pointer-pushing, then why on earth does the compiler not just implement new? I think you need to ask questions tagged with your specific compiler and platform, so that any experts on your compiler can respond.

Upvotes: 4

laalto
laalto

Reputation: 152817

Placement new does everything a regular new would do, except allocate memory.

I think you've essentially nailed what happens, with some minor clarifications:

  • obviously the constructor of the class itself is called as well
  • vtable pointers are initialized as part of constructor calls, not separately. An implication of this is that a partially constructed object (think exceptions thrown in constructor) has its vtable set up to the point the construction proceeded to.

The order of construction/initialization is as follows:

  1. virtual base classes in declaration order
  2. nonvirtual base classes in declaration order
  3. class members in declaration order
  4. class constructor itself

Upvotes: 6

Related Questions