https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95349
--- Comment #43 from Richard Biener <rguenth at gcc dot gnu.org> --- (In reply to Andrew Downing from comment #41) > > Thus for types without a non-trivial ctor/dtor you do not need to use > > placement new. So take your example and remove the placement new. > > Does that change its semantics? > > These are C++17 rules. > > 4.5/1) An object is created by a definition, by a new-expression, when > implicitly changing the active member of a union, or when a temporary object > is created. > > 6.8/1) The lifetime of an object of type T begins when: storage with the > proper alignment and size for type T is obtained, and if the object has > non-vacuous initialization, its initialization is complete. > > double d; > > My interpretation of the above rules would be that only a double object is > created in the storage for d because T in 6.8/1 is set to double by the > definition of d. According to these rules the only way to change the dynamic > type of the object in d's storage would be with placement new (pre C++20). > memcpy only overwrites the object representation. It doesn't affect it's > type or lifetime. What would *(long *)&d = 1; do? My reading of earlier standards say it starts lifetime of a new object of type long (the storage of 'd' gets reused). Following that stmt a read like foo (d); invokes undefined behavior (it accesses the storage of effective type long via an effective type of double). The same example with placement new would be *(new (&d) long) = 1; and I'm arguing the placement new is not required to start the lifetime of an object of type long in the storage of 'd'.