Вызывает ли деструктор явное уничтожение объекта полностью?

Если я вызываю деструктор явным образом (myObject. ~ Object ()), гарантирует ли это, что объект будет надлежащим образом уничтожен (вызывая все дочерние деструкторы)?

Хорошо, некоторый код:

<code>class Object
{
   virtual ~Object()
   {}
};

class Widget : public Object
{
   virtual ~Widget()
   {}
};

...
Object* aWidget = new Widget(); //allocate and construct
aWidget->~Object(); //destroy and DON'T deallocate
</code>

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

Спасибо!

Ответы на вопрос(11)

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

Да. Деструктор вызывает любые члены-деструкторы в порядке LIFO, затем деструкторы базового класса, и нет никакого способаprevent это от вызова этих деструкторов *. Стек объектов гарантированно раскручивается.

Инициализация и финализация отделены от выделения и освобождения памяти в C ++ именно так, что при возникновении особого случая существует однозначный синтаксис, в котором программист приложения может выразить свое намерение компилятору.

Редактировать:

I suppose that by invoking abort() or longjmp() one could, in fact, prevent the member and base class destructors from running.

Запуск деструктора не освобождает память, используемую разрушаемым объектом - это делает оператор удаления. Однако обратите внимание, что деструктор может удалять «дочерние объекты» и их память будет освобождена, как обычно.

Вы должны прочитать о размещении new / delete, так как это позволяет вам контролировать распределение памяти и когда запускаются конструкторы / деструкторы.

Смотрите здесь для небольшой информации:

http://www.parashift.com/c++-faq-lite/dtors.html#faq-11.9

Пожалуйста, избавьте себя от реальных головных болей и используйтеBoost Object Pool, который звучит как существующая реализация вашего шаблона источника / приемника. Он выделит большие куски памяти, разделит их на правильный размер для вашего объекта и вернет их вам (после вызова конструктора). Когда вы удаляете объекты, им вызывается деструктор, и они помещаются в связанный список объектов для повторного использования. Он будет автоматически увеличиваться и уменьшаться и гарантировать, что экземпляры ваших объектов имеют тенденцию быть близко друг к другу в памяти.

Если ничего другого, то это хороший пример реализации размещения нового и явного использования конструкторов, которые вы могли бы изучить.

Да, деструктор, даже при явном вызове, будет правильно уничтожать свои подобъекты.

Как вы, кажется, понимаете, это редкое действие, но, возможно, как часть хорошо протестированной и документированной библиотеки, это может быть полезно. Но задокументируйте (и профилируйте) его, поскольку, несмотря на то, что он действителен и безопасен, каждый сопровождающий (включая вас) никогда не будет чувствовать себя комфортно с ним.

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

Да, он вызовет все дочерние деструкторы, поэтому он будет работать так, как вы ожидаете.

В конце концов, деструктор - это просто функция, так бывает, что он вызывается, когда объектыare deleted.

Поэтому, если вы используете этот подход, будьте осторожны с этим:

#include <iostream>

class A
{
public: 
    A(){};
    ~A()
    {
        std::cout << "OMG" << std::endl;
    }
};

int main()
{
    A* a = new A;
    a->~A();
    delete a;
    return 0;
}

output:
OMG
OMG 

Деструктор вызывается второй раз, когда на самом деле вызывается delete для объекта, поэтому, если вы удаляете указатели в своем деструкторе, убедитесь, что вы установили их в 0, так что во время вызова деструктора ничего не произойдет (как удаление нулевого значения). указатель ничего не делает).

Вызов деструктора - это хорошо. Однако остерегайтесь того типа, который вы вызываете. Если этот тип не имеет (не наследовал) виртуального деструктора, вы можете получить неожиданное поведение.

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

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

Да. Но святой дым, вы уверены в этом? Если так, то я бы использовалразмещениеnew построить свойWidget, Использование размещенияnew и затем явный вызов деструктора - приемлемая, хотя и необычная, идиома.

Edit: Рассмотрите возможность выделения памяти вручную, а не используяnew выделить первый объект, а затем повторно использовать его память. Это позволяет вам полностью контролировать память; Например, вы могли бы выделять большие порции за раз, вместо того, чтобы выделять отдельный блок памяти для каждогоWidget, Это было бы справедливой экономией, если бы память действительно была таким дефицитным ресурсом.

Кроме того, и, возможно, что еще более важно, вы затем будете заниматься размещениемnew "нормально", а не этот гибридный регулярныйnew/ размещениеnew решение. Я не говорю, что это не сработает, я просто говорю, что это скорее, ах,creative Решение вашей проблемы с памятью.

Ответ ... почти всегда.

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

У нас был интересный случай, когда две общие библиотеки ссылались на объект. Мы изменили определение, чтобы добавить дочерние объекты, которые нуждались в освобождении. Мы перекомпилировали первую разделяемую библиотеку, которая содержала определение объекта.

ОДНАКО, вторая общая библиотека не была перекомпилирована. Это означает, что он не знал о недавно добавленном определении виртуального объекта. Удаление вызывается из второй общей библиотеки, просто называемой свободной, и не вызывает цепочку виртуальных деструкторов. Результатом стала неприятная утечка памяти.

Контейнеры STL делают это. Фактически, распределитель STL должен предоставлять метод уничтожения, который вызывает деструктор объекта (allcators также предоставляет метод освобождения для освобождения памяти, которая использовалась для хранения объекта). Однако совет от Страуструпа (The C++ Programming Language 10.4.11) есть

Note that explicit calls of destructors ... should be avoided wherever possible. Occassionally, they are essential. ... A novice should think thrice before calling a destructor explicitly and also ask a more experienced colleague before doing so.

ВАШ ОТВЕТ НА ВОПРОС