36

How can I call a constructor on a memory region that is already allocated?

peterh
  • 11,875
  • 18
  • 85
  • 108
Ben
  • 7,372
  • 8
  • 38
  • 46

3 Answers3

56

You can use the placement new constructor, which takes an address.

Foo* foo = new (your_memory_address_here) Foo ();

Take a look at a more detailed explanation at the C++ FAQ lite or the MSDN. The only thing you need to make sure that the memory is properly aligned (malloc is supposed to return memory that is properly aligned for anything, but beware of things like SSE which may need alignment to 16 bytes boundaries or so).

Vaillancourt
  • 1,380
  • 1
  • 11
  • 42
Anteru
  • 19,042
  • 12
  • 77
  • 121
  • 6
    For anyone else who stumbles across this: I had to `#include ` before this would work - g++ threw a bunch of unhelpful "no matching function" errors if I didn't. [This](http://www.parashift.com/c++-faq-lite/dtors.html#faq-11.10) is the info on placement new (also C++ FAQ) that helped me figure it out. – Xavier Holt Mar 21 '11 at 01:22
  • 2
    "The only thing" -- there are also other concerns, for example reusing the memory location containing an active object with a non-trivial destructor can lead to undefined behaviour. [See this question](https://stackoverflow.com/questions/42997440/is-it-legal-to-use-placement-new-on-initialised-memory) for more detail – M.M Jun 15 '20 at 22:43
  • @M.M doesn't std::launder solve that ? – 0xB00B Feb 06 '22 at 07:44
5

Notice that before invoking placement new, you need to call the destructor on the memory – at least if the object either has a nontrivial destructor or contains members which have.

For an object pointer obj of class Foo the destructor can explicitly be called as follows:

obj->~Foo();
Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • 3
    Why should we call the destructor on the newly allocated memory before doing the placement new ? I dont get it... – Malkocoglu Feb 06 '09 at 12:29
  • 1
    You normally don't get memory that has been allocated but not initialized. If that's indeed what you've got then of course you *must not* call a destructor on it. For all other cases, there is already an object at that location that must be properly disposed of. – Konrad Rudolph Feb 06 '09 at 12:39
  • 1
    You don't initialize memory(unless you mean setting all zeroes). You initialize objects. Calling dtor on some random memory is bad. Only if you are doing container of objects it would make sense to call dtor. If these objects have empty non-virtual dtor you dont have to do it. – Arek Bal Nov 01 '14 at 00:54
  • @ArekBal Object = memory, according to the C++ standard. So you initialise both. Of course if you have *uninitialised* memory you wouldn’t call the destructor (but that’s *still* an object). And like I said in my answer, the presence of an empty destructor isn’t enough to forego calling the destructor, since member variables may have non-trivial destructors. – Konrad Rudolph Nov 01 '14 at 20:18
4

The placement new constructor mentioned by the accepted answer is an old way before the allocator class defined in header. Now you really should do(in C++11 style):

allocator<Foo> alloc;
//Allocate memory for one or n objects
auto p = alloc.allocate(1); 
//Construct an object of Foo on allocated memory block p, by calling one of Foo's constructors
alloc.construct(p, args, ...); 

//OK, p now points to a Foo object ready for use...

//Call Foo's destructor but don't release memory of p
alloc.destroy(p); 
//Release memory
alloc.deallocate(p, 1); 

That's it.

Robert
  • 1,964
  • 1
  • 22
  • 22
  • `std::allocator::construct` is for instantiating objects in memory supplied by `std::allocator::allocate`, not arbitrary other sources – Caleth Jun 15 '20 at 23:14
  • Are you sure? @Caleth – Robert Jun 18 '20 at 04:01
  • @Robert In C++20 you can use [`std::construct_at`](https://en.cppreference.com/w/cpp/memory/construct_at) and it's not part of `allocator` namespace anymore – joepol Nov 04 '22 at 19:42