There is no need for the allocating new
here. You just need to make sure that you have an array of sufficient size and alignment:
alignas(display) std::byte memory[sizeof(display)];
display *obj = nullptr;
(Instead of std::byte
you can use unsigned char
, but I think std::byte
, which is available since C++17, expresses the intent as raw memory storage better.)
Then construct the object with
obj = new(memory) display(a);
and when it is not needed anymore, call its destructor explicitly:
obj->~display();
No delete
is needed in this case. With your approach an additional delete[] memory;
after the destructor call would be required to free the memory allocated with the first new
, if you don't intent to reuse it after the destructor call (which you can do e.g. in a loop constructing a new display
with placement-new). Note that you need to call the destructor on obj
and the delete[]
on memory
. This is not interchangeable. memory
is a pointer to the allocated memory block and obj
a pointer to the object nested in it. The former was allocated with allocating new[]
, so required delete[]
, and the latter was only created with the (non-allocating) placement-new, so requires only an explicit destructor call.
Of course, you can consider whether the destructor call is really needed. If the display
doesn't hold any resources that need to be cleaned up, then you can skip it, although I would be safe and call it anyway, just in case display
will be changed later.
Also, the standard library since C++17 implements all of this as std::optional
. If you can use it, then do so:
std::optional<display> obj;
// obj is now empty, can be tested with `if(obj)`
obj.emplace(/* constructor arguments */);
// obj now contains a display that can be accessed like a pointer with * and ->
// destructor of obj will take care of correctly destroying the display
emplace
can also be called multiple times to replace the display
with a new one (and calling the old one's destructor) or .reset()
can be used to explicitly empty the optional
.
If you don't have C++17 available, a std::unique_ptr
can be used in a similar way, except that it will use a heap allcoation, which std::optional
doesn't, and that std::unique_ptr
isn't copyable even if display
is, while std::optional
will be.
std::optional<display> obj;
// obj is now empty, can be tested with `if(obj)`
obj = std::make_unique<display>(/* constructor arguments */);
// obj now contains a display that can be accessed like a pointer with * and ->
// destructor of obj will take care of correctly destroying the display
obj
can be reassigned in that way multiple times as well or reset with = nullptr;
or .reset()
and in either case it will take care of correctly destroying any display
just like std::optional
does.