Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it defined behavior to use placement new to change type of variable that is held by reference_wrapper?

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?

like image 658
xinaiz Avatar asked Feb 24 '17 20:02

xinaiz


1 Answers

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".

like image 108
T.C. Avatar answered Nov 15 '22 17:11

T.C.