https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61982
--- Comment #12 from Jonathan Wakely <redi at gcc dot gnu.org> --- The C++ standard. Specifically, [basic.life]. After the constructor runs and before the destructor runs, that memory location contains an object of type X. After the destructor finishes you can reuse the storage for another object. The memcmp calls treats the storage as an array of unsigned char and can implicitly begin the lifetime of an array of unsigned char because unsigned char does not have non-vacuous initialization (i.e. it doesn't need to be initialized). However, if you don't initialize those characters then they have indeterminate values. So the first memcmp call reuses the storage to create an array of unsigned char with indeterminate values. That ends the lifetime of the X (without calling the destructor). Then you call the destructor on an object that already ended its lifetime, which is undefined. Then you reuse it as an array of unsigned char again, and it still has indeterminate values. Even if we ignore the UB caused by invoking the destructor for an object that no logner exists, the value representation of the X cannot be inspected by memcmp, because X is not trivially copyable, and since the values are indeterminate there is no requirement for the values written by the destructor to be observable.