|
Уничтожение с разделением фаз Объект, переданный в качестве аргумента оператору 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. Вам придется сделать это самостоятельно, используя только что описанную методику. |
Copyright 2005. Климов Александр. All Right Reserved.