Accessing objects via reinterpret_cast
ed pointers and related UB has been extensively discussed here. After reading questions and answers, I'm still not sure about proper using uninitialized memory with POD types.
Suppose I want to "emulate"
struct { double d; int i; };
by manually allocating memory for data members and suppose (for simplicity) that no padding is needed before i
.
Now, I do this:
// (V1)
auto buff = reinterpret_cast<char*>(std::malloc(sizeof(double) + sizeof(int)));
auto d_ptr = reinterpret_cast<double*>(buff);
auto i_ptr = reinterpret_cast<int*>(buff + sizeof(double));
*d_ptr = 20.19;
*i_ptr = 2019;
First question: is this code valid?
I could use placement new
:
// (V2)
auto buff = reinterpret_cast<char*>(std::malloc(sizeof(double) + sizeof(int)));
auto d_ptr = new(buff) double;
auto i_ptr = new(buff + sizeof(double)) int;
*d_ptr = 20.19;
*i_ptr = 2019;
Do I have to? Placement new
seems to be redundant here because default initialization of POD types is no-op (vacuous initialization), and [basic.life] reads:
The lifetime of an object of type
T
begins when:(1.1) storage with the proper alignment and size for type
T
is obtained,(1.2) if the object has non-vacuous initialization, its initialization is complete, ...
Does this say that the lifetime of *d_ptr
and *i_ptr
objects began once I had allocated memory for them?
Second question: can I use type double*
(or some T*
) for buff
, i.e.
// (V3)
auto buff = reinterpret_cast<double*>(std::malloc(sizeof(double) + sizeof(int)));
auto d_ptr = reinterpret_cast<double*>(buff);
auto i_ptr = reinterpret_cast<int*>(buff + 1);
*d_ptr = 20.19;
*i_ptr = 2019;
or
// (V4)
auto buff = reinterpret_cast<double*>(std::malloc(sizeof(double) + sizeof(int)));
auto d_ptr = new(buff) double;
auto i_ptr = new(buff + 1) int;
*d_ptr = 20.19;
*i_ptr = 2019;
?