https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77896
--- Comment #4 from Ryan Johnson <scovich at gmail dot com> --- Yikes. That explains it, all right. I never would have thought of an object destroying itself and changing its type with placement new... I guess it must be subject to the same restrictions as `delete this` [1], because things don't turn out well if the compiler thinks it knows the type of the object: ==== alter.cpp ======= #include <cstdio> #include <new> struct AlterEgo { virtual ~AlterEgo() { } virtual void toggle()=0; }; struct Jekyl : AlterEgo { ~Jekyl() { puts("~Jekyl"); } void toggle(); }; struct Hyde : AlterEgo { ~Hyde() { puts("~Hyde"); } void toggle(); }; void Jekyl::toggle() { this->~AlterEgo(); new (this) Hyde; } void Hyde::toggle() { this->~AlterEgo(); new (this) Jekyl; } void whatami(AlterEgo* x) { printf("Jekyl? %p\n", dynamic_cast<Jekyl*>(x)); x->toggle(); printf("Jekyl? %p\n", dynamic_cast<Jekyl*>(x)); } int main() { puts("\nWorks ok-ish:"); Jekyl* x = new Jekyl; whatami(x); puts("\nJekyl?"); delete x; puts("\nBad idea:"); Jekyl j; j.toggle(); j.toggle(); whatami(&j); puts("\nJekyl?"); } ==================== $ g++ -Wall alter.cpp && ./a.out Works ok-ish: Jekyl? 0x6000104c0 ~Jekyl Jekyl? 0x0 Jekyl? ~Hyde Bad idea: ~Jekyl ~Hyde Jekyl? 0x0 ~Hyde Jekyl? 0xffffcbf0 Jekyl? ~Jekyl [1] https://isocpp.org/wiki/faq/freestore-mgmt#delete-this