В C++20 завезли destroying delete operator. Его основное отличие от обычного delete -- что при удалении через destroying delete вы сначала заходите в функцию, где сами должны вызвать деструктор



struct Foo {

~Foo() {

std::cout << "In Bar::~Bar()\n";

}



void operator delete(Foo* p, std::destroying_delete_t) {

std::cout << "In Foo::operator delete(Foo*, std::destroying_delete_t)\n";

p->~Foo();

::operator delete(p);

}

};




https://gcc.godbolt.org/z/zqd8Yn7ff



Из интересного, вы теперь можете сами писать свои vtable: https://gcc.godbolt.org/z/EYMn1sd1o



struct Vehicle {

const enum Types { CAR, TRUCK } type;

Vehicle(Types t) : type(t) {}

void operator delete(Vehicle*, std::destroying_delete_t);

};

// Implement Car, Truck



void Vehicle::operator delete(Vehicle *p, std::destroying_delete_t) {

switch (p->type) {

case CAR:

static_cast<Car*>(p)->~Car();

break;

case TRUCK:

static_cast<Truck*>(p)->~Truck();

break;

}

::operator delete(p);

}




Когда вы можете писать свои vtable, вы можете классы инициализировать через memset и тд, потому что вы убираете полную инициализацию.



Например, протобуфы. Все они наследуются от MessageLite, а теперь в кодогенерации можно свою vtable написать и инициализировать все поля быстро через mem*. До этого это было undefined behavior из-за нефиксированности имплементации vtable.



https://en.cppreference.com/w/cpp/memory/new/operator_delete. Cм 27-30.