I've seen some examples of placement new, and am a little confused as to what's happening internally with the various types.
A simple example:
using my_type = std::string;
using buffer_type = char;
buffer_type buffer[1000];
my_type* p{ new (buffer) my_type() };
p->~my_type();
From what I understand, this is valid, though I'm concerned about what happens to the char array of buffer[]
. It seems like this is ok to do as long as I don't access the variable buffer
in any form after creating a new object in place on its memory.
For the sake of keeping this simple, I'm not concerned about anything to do with proper alignment here, or any other topics of what can go wrong when calling placement new other than: what happens to the original type? Could I use another type such as buffer_type = int
to achieve a similar effect (ignoring the possibility of how much memory that will actually take)? Is any POD safe as buffer_type
? How about non-POD types? Do I have to tell the compiler that the char array is no longer valid in some way? Are there restrictions on what my_type
could be or not be here?
Does this code do what I expect it to, is it well defined, and are there any minor modifications that would either keep this as well defined or break it into undefined behaviour?
You mean the original object? It get's destroyed, that is, its lifetime ends. The lifetime of the array object of type
buffer_type [1000]
ends as soon as you reuse its storage.Note that this implies that we should not use something with a non-trivial destructor for the buffer: The elements' destructors are called at the end of the scope it's defined in. For e.g.
std::string
as the element type that would imply a destructor call on an non-existing array subobject, which clearly triggers undefined behavior.To avoid that you would have to construct
std:string
s into that buffer after you're done with it, which really seems nonsensical.We do not necessarily need PODs - they have a lot of requirements that are not a necessity here. The only things that bother us are the constructor and the destructor.
It matters whether the types destructor is trivial (or for an array, the arrays element types' destructor). Also it's feasible that the constructor is trivial, too.
POD types feel safer since they suffice both requirements and convey the idea of "bare storage" very well.
Yes. It shall be an object type. It can be any object type, but it cannot be a reference.