Усі відповіді описують конкретні випадки, але є загальна відповідь:
Ви викликаєте dtor явно кожного разу, коли вам потрібно просто знищити об'єкт (у сенсі C ++), не звільняючи пам'яті, в якій знаходиться об'єкт.
Зазвичай це трапляється в усіх ситуаціях, коли розподілом / вивільненням пам'яті управляється незалежно від побудови / руйнування об'єкта. У цих випадках будівництво відбувається шляхом розміщення нового на існуючому фрагменті пам'яті, а знищення відбувається за допомогою явного дзвінка dtor.
Ось необроблений приклад:
{
char buffer[sizeof(MyClass)];
{
MyClass* p = new(buffer)MyClass;
p->dosomething();
p->~MyClass();
}
{
MyClass* p = new(buffer)MyClass;
p->dosomething();
p->~MyClass();
}
}
Іншим помітним прикладом є значення за замовчуванням std::allocator
при використанні std::vector
: елементи будуються в vector
під час push_back
, але пам'ять виділяється шматками, тому вона вже існує для створення елементів. А отже, vector::erase
повинен знищити елементи, але не обов'язково це звільняє пам'ять (особливо якщо новий push_back повинен відбутися незабаром ...).
Це "поганий дизайн" у суворому ООП-розумінні (ви повинні керувати об'єктами, а не пам'яттю: факт, що об'єкти вимагають пам'яті, - це "інцидент"), це "хороший дизайн" у "програмуванні низького рівня" або у випадках, коли пам'ять не взято з "безкоштовного магазину" за замовчуванням operator new
купується в.
Це поганий дизайн, якщо це відбувається випадково навколо коду, це хороший дизайн, якщо це відбувається локально для класів, спеціально розроблених для цієї мети.