What is this weird constructory syntax C::C()?


The Microsoft Visual C++ compiler supports this weird thing:

// assume a class C has been defined
C* p = (C*)malloc(sizeof(C));
p->C::C(); // huh?

This weird syntax is how people in olden times explicitly invoked a constructor on an uninitialized block of memory.

Then placement new arrived on the scene and made the above syntax obsolete.

// new hotness
C* p = (C*)malloc(sizeof(C));
new(p) C();

But the Microsoft Visual C++ compiler still supports the old syntax for backward compatibility purposes.

Note that the corresponding explicit destructor syntax

p->C::~C(); // can be shortened to p->~C() if p is of type C*

is still standard as of this writing.

Comments (19)
  1. Gee Law says:

    The semantics for p->C::~C() and p->~C() are different, even if decltype(p) is C *. The former bypasses virtual destructor invocation, which is the same syntax for accessing unambiguous base class member (bypass name shadowing and virtual table look-up).

    1. Chunsheng Pei says:

      I verified that p->C::~C() is semantically equal to p->~() (gcc 4.8.0). Both calls the virtual dctor of the base class.

      1. Gee Law says:

        Did you mean p->~C() by p->~()? I don’t have g++ 4.8.0 at hand but I just tried the two (C::~C and ~C) again on g++ 6.3.0-1 (mingw) and MSVC++ 19.14.26429.4. For C::~C, both called the implementation in the declared type (instead of the runtime type). Actually, “the virtual dtor of the base class” confuses me. If a function is virtual, it is no longer “the function of a class”, and that’s why it’s virtual. I interpreted your phrase as “the implementation of the virtual dtor in the base class”.

  2. Ben Voigt says:

    Important to note, the old syntax is more than just “obsolete”, it’s explicitly excluded by recent (and not-so-recent) C++ language standards.

  3. rfog says:

    And why not? That is what the compiler does when you use new/delete operators. ;-)

  4. AberAber says:

    For my knowledge, when would you ever use this malloc/constructor thing syntax instead of? The difference I can see is that perhaps you can explicitly call deconstructor, instead of using scope?
    C* p = new C();

    1. kantos says:

      Short answer: Containers, if you’re allocating a contiguous buffer you might use placement syntax if you absolutely hate allocators for some reason (some people have a pathological hatred for them for inexplicable reasons).

      1. Martin Bonner says:

        … or you’re writing an allocator. Placement new is how the allocator has to create the object in the buffer it has allocated.

    2. Pietro Gagliardi (andlabs) says:

      Placement new is used if you have a block of memory that can hold a C, but it wasn’t created by the other C++ object construction mechanisms. For instance, let’s say for whatever reason you have to use CoTaskMemAlloc() and CoTaskMemFree() for some memory, and you want that memory to hold a C++ class. You can thus say

      C *p = (C *) CoTaskMemAlloc(sizeof (C));
      new (p) C(constructor parameters);

      and then you can safely use p as if it was allocated by the new operator itself. I use CoTaskMemAlloc() specifically because I imagine there are some situations when you need to allocate a COM object on the COM heap. If your object is a C++ class, then the above code is what you would be using to return your COM object. However, I have not yet written enough COM to know if this is actually what people do in the real world. This is just the most realistic general-purpose example I can come up with (everything else I can think of right now would be contrived).

      And yes, you do need to explicitly call the constructor/use placement new, because if any field in your class is itself a class, that class will ned ot be constructed too, and your class’s constructor will, directly or indirectly, take care of that for you.

      1. Ben Voigt says:

        The cast there is harmful. A pointer to the object is gotten from the result of the `new` operator, and has type `C*`. The pointer handed to the new operator, conversely, is merely raw storage, so the most appropriate type is `void*`.

  5. Alois Kraus says:

    One good usage of this is for a tracing system where the ctor is omitted when tracing is off. Since the dtor can check via a global flag if tracing was enabled it will not trigger anything bad when the object is destroyed. This only works if you have only basic and pointer members. Otherwise the dtor of the members will crash you anyway. Many years ago this was a worthwile performance optimization for a C++ tracing framework.

  6. Martin Bonner says:

    Is it just me, or does anyone else find the old syntax for explicitly invoking the constructor more obvious than the new? I particularly like the way it mirrors explicit delete.

    (This is the first time I remember seeing the old syntax, and I have been using C++ since 1994.)

    1. rfog says:

      … and then, one day, you receive a phone call after typed the malloc line and forgot to type the call to constructor… and you get a very beautiful app crash. ;-)

      Not only use new, but use auto-pointers.

  7. henke37 says:

    Don’t you still need to manually call constructors for union members? I must be rusty, because I thought that was the way to do it.

    1. Darran Rowe says:

      You call placement new on the union’s data member.

  8. Vlad says:

    std::destory_at(p) is much better than writing down the type manually as in p->~TYPE_OF_P_IF_YOU_GET_IT_RIGT()

  9. exim says:

    There is `new` operator variant (standard) that doesn’t call the constructor.

  10. Anonymous says:

    (The content was deleted per user request)

  11. Karl says:

    Please remove this from VS++. ASAP.

Comments are closed.

Skip to main content