4

The context is: Writing a container, containing type T, and a char * p to a memory region. Let's suppose the pointer is already suitably aligned for type T - the alignment issue is not part of the question. How do I default construct an element on that memory region?

((*T)(p))->T();

works for classes, but not with some builtin types.

((*T)(p)) = 0; // or simply memset

for integral types, pointers. Do these two cover everything, unions and what not? Is there a best practice for this, or some standard library feature? std::allocator::construct can do it, that is what e.g. std::vector uses, but it is not a static method, so I would need an instance of it. Is there some freestanding or static function that can do it?

--EDIT--

Yes, the answer is obvious, and I was dumb today -- placement new BTW, Now I'm trying to destroy the element...

Gábor Buella
  • 1,840
  • 14
  • 22
  • 6
    Placement new: `new (p) T();` – Kerrek SB Oct 15 '15 at 21:35
  • 2
    That first snippet should not compile... – Brian Bi Oct 15 '15 at 21:35
  • See http://stackoverflow.com/questions/222557/what-uses-are-there-for-placement-new – sehe Oct 15 '15 at 21:37
  • Concerning the edit: There is no `delete` equivalent for placment-new. For classes, pure destruction is done by an explicit destructor call `myFooPtr->~Foo();`. Unfortunately, this does not seem to work for builtin types, so I guess, you are out of luck at that point. However, since you seem not to be afraid of heavy templates, you might use SFINAE to distinguish between the cases that a destructor can or cannot be called, and instanciate code with/without such a destructor call accordingly (builtin types don't need destruction). Beware of array types, though! – cmaster - reinstate monica Oct 15 '15 at 22:01

2 Answers2

3

"Placement new" is the term to look for. It is a standard library operator new overload that does not actually allocate memory, but just returns whatever pointer you pass to it.

  • this very closely resembles a comment. In fact it closely resembles the comment that is also already there. – sehe Oct 15 '15 at 21:36
  • @sehe Look at the timestamps. I was clearly already typing my answer when that comment was posted. –  Oct 15 '15 at 21:37
  • Now I'm trying to destroy the item... back to square one – Gábor Buella Oct 15 '15 at 21:40
  • You can explicitly call the destructor for that. –  Oct 15 '15 at 21:42
  • @BuellaGábor you can call the destructor of an object from a pointer to the object with `myfooptr->~Foo();` – jaggedSpire Oct 15 '15 at 21:42
  • placement new works for builtin types as well as for classes, but int has no destructor.... – Gábor Buella Oct 15 '15 at 21:45
  • 1
    @BuellaGabor Look up "pseudo-destructor call". I am guessing you tested with a simple typedef. In that case you already know in advance that you do not need to call the destructor. In the general case, when `T` is not known in advance, the syntax gets accepted even for simple types. –  Oct 15 '15 at 21:58
  • right, it works, I just had a typo before. I'v never heard of a pseudo destructor before, thx! – Gábor Buella Oct 15 '15 at 22:02
3

Include the <new> header and use its placement new allocation function like this:

::new (p) T()

The :: qualification avoids picking up a class-specific allocation function.

The paranthesis (p) is an argument list for the allocation function.

This allocation function just returns the passed in pointer.

To be pedantic about things you would also cast the pointer to void*, to avoid picking up some hypothetical other operator new in the global namespace.


The code shown in the question, ((*T)(p))->T();, should not compile. The standard explicitly points out that a constructor doesn't have a name. So it can't be called like an ordinary function.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331