Очистка в методе Shutdown() вместо деструктора

В руководствах по Rastertek DirectX они содержат пустые конструкторы и деструкторы и вместо этого используют initialize() а также shutdown() функции для инициализации и очистки объектов. После использования этого дизайна в течение некоторого времени я могу понять преимущества наличия initialize() метод, но я не вижу, как с помощью shutdown() метод лучше, чем поместить весь код очистки в деструктор.

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

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

Таким образом, общая схема использования выглядит следующим образом:

class Renderer
{
public:
    Renderer() { }
    ~Renderer() { }

    bool initialize(...) { /* perform initialization */ }
    void shutdown() { /* clean-up */ }
}; 

Renderer* renderer = new Renderer;
renderer->initialize(...);

// use the renderer

renderer->shutdown();
delete renderer;
renderer = NULL;

Когда я смотрю на код Растертека, мне кажется, что они исходят из C-фона (инициализируют все переменные в верхней части функции, используют только необработанные указатели и необработанные массивы и т. Д.), Поэтому мне интересно, не является ли это еще одной вещью, которая ненужный в современном C++ (с одной стороны, это затрудняет использование умных указателей). Есть ли реальная выгода для этого дизайна?

1 ответ

Решение

Как правило, это плохой совет не делать очистку в деструкторе.

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

Кстати, пример кода действительно похож на того, кто пришел из мира c.

Причина в том, что я не доверяю тому, чтобы меня называли. Некоторые функции Windows, такие как ExitThread(), известны тем, что не вызывают деструкторы вашего класса, что приводит к утечкам памяти.

Это правильно, но старайтесь избегать таких функций. Также отсюда:

В C++11 (о котором я знаю) не существует переносимого способа некооперативного уничтожения одного потока в многопоточной программе (т.е. без уничтожения всех потоков).

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

Другие вопросы по тегам