Материалы книги получены с http://www.itlibitum.ru/
Уничтожение с разделением фаз
Объект, переданный в качестве аргумента оператору delete, обычно уничтожается компилятором в два этапа:
1. Вызов деструктора.
2. Вызов оператора delete для освобождения памяти.
Довольно часто мы качаем головой и говорим: «Хорошо бы вызвать деструктор, но не трогать память». Допустим, вы разместили объект в пуле, а теперь не хотите, чтобы часть локально созданного пула вернулась в главное хранилище памяти. По аналогии с тем, как мы разделили двухшаговый процесс конструирования, можно разделить и двухшаговый процесс уничтожения, напрямую вызывая деструкторы. Однако в отличие от тех выкрутасов, которыми сопровождалось разделение процесса конструирования, с уничтожением дело обстоит очень просто - достаточно вызвать деструктор так, словно это обычная функция класса.
void f()
{
Pool localPool;
Foo* foo1 = new Foo; // Использует оператор new по умолчанию
Foo* foo2 = new(&localPool) Foo; // Использует перегрузку
delete foo1; // Для оператора new по умолчанию
foo2->~Foo(); // Прямой вызов деструктора
}
localPool - большой блок памяти, локальный по отношению к функции. Поскольку он создается в стеке, при завершении f() он выталкивается из стека. Выделение происходит молниеносно, поскольку локальные объекты заполняют пул снизу вверх. Освобождение происходит еще быстрее, поскольку уничтожается сразу весь пул. Единственная проблема заключается в том, что компилятор не будет автоматически вызывать деструкторы объектов, созданных внутри localPool. Вам придется сделать это самостоятельно, используя только что описанную методику.
Назад Содержание Далее
|