I was messing with placement new, and made this code:
#include <iostream>
#include <functional>
#include <new>
int main()
{
char memory[sizeof(int)]; //memory to hold type
auto ref = std::ref(*new (memory) int{5}); //allocating int in memory, and make a reference to it
std::cout << ref << std::endl;
new (memory) unsigned{6}; //"overwrite"
std::cout << ref << std::endl;
}
The output is 5
then 6
, but is it well defined? If so, would it be okay if I used float
as second type instead?
The second placement new-expression reuses the storage of, and therefore ends the lifetime of, the int
object created by the first placement new-expression ([basic.life]/1.4).
Since [basic.life]/8 isn't satisfied (due to the type difference), the pointer stored by the reference wrapper doesn't point to the new object, but continues to point to the out-of-lifetime int
object. Accessing the object via an lvalue obtained from such a pointer therefore has undefined behavior per [basic.life]/7.
Note that strict aliasing is irrelevant here; that rule explicitly permits accessing an object via a glvalue of "a type that is the signed or unsigned type corresponding to the dynamic type of the object".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With