Допустимо ли напрямую вызывать (виртуальный) деструктор? - PullRequest
7 голосов
/ 17 мая 2011

В этом ответе Райан напрямую вызывает виртуальный деструктор.Я протестировал код в VS2010, и он правильно вызывает все деструкторы (проверено с помощью операторов логирования).Это действительно так?В чем проблемы, недостатки или даже плюсы такого подхода?

Я могу думать только об этом, как о способе принудительного сброса фактического типа, даже если они не перекрывают виртуальныйreset, так как они, по крайней мере, должны очистить свои деструкторы.

Кроме того, какие именно побочные эффекты приносит вызов деструктору?Является ли неопределенным поведение использовать объект после такого вызова деструктора?Что, если сразу же повторно инициализировать его с помощью вызова new (this) MyClass();?

Ответы [ 3 ]

4 голосов
/ 17 мая 2011

Вызов деструктора вручную - совершенно правильная вещь, независимо от того, виртуален ли он.Вы просто хотите убедиться, что он вызывается один раз для каждого вызова конструктора.

Is it undefined behaviour to use the object after such a destructor call? 

Да.

What if one immediatly reinitializes it with a new (this) MyClass(); call?

Все еще ужасно неопределен.

Не уничтожать вручнуюобъект, если вам не пришлось вручную его размещать, например, с помощью нового или какого-либо эквивалентного размещения, и определенно никогда не инициализировать разрушенный объект подобным образом и надеяться избежать UB.Такие классы, как std::vector, очень явно делают доступ к разрушенным объектам UB, и он остается UB, даже если вы создадите новый элемент вместо него.

1 голос
/ 17 мая 2011

Пример правильного использования, включающего одну и только одну конструкцию:

typedef boost::aligned_storage<
    sizeof(T), boost::alignement_of<T>::value>::type arena_type;
arena_type arena;
T* p = new (&arena) T();
p->~T();
// Don't touch p now

Это может быть полезно, например, при реализации типа варианта ( предупреждение : исключение-безопасность оставлено в качестве упражнениячитателю).Неограниченные объединения C ++ 0x будут иметь аналогичное использование для типов классов.

Обратите внимание, что для типа класса выше будет UB, если вы not вызовите деструктор.

0 голосов
/ 17 мая 2011

Пока вы вызываете размещение нового поверх предварительно выделенного фрагмента памяти POD, вполне допустимо освобождать, вызывая любой деструктор, виртуальный или нет.

размещение новогои явный вызов освобождения просто вызовет конструктор и деструктор в ссылочных областях, поэтому выделение памяти эффективно исключается из жизненного цикла объекта

...