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

Могу ли я быть уверен, что деструктор вызван? Меня особенно беспокоят случаи, когда а) testCondition истинно, и функция рано возвращается из внутренней области видимости, в которой был построен tempObj б) во время выполнения этой функции возникает некоторая ошибка времени выполнения (которая обнаруживается на более высоком уровне)

(В качестве побочного вопроса: это хороший способ временно сохранить некоторые данные? В моем приложении someFunc() является функцией сохранения / экспорта текущей базы данных.)

class TempStore
{
public:
    TempStore() {/* delete some stuff from a db and store this in memory*/}
    ~TempStore() {/* write this stuff back into the db*/}
};

void someFunc(bool testCondition)
{
    TempStore tempObj = TempStore();
    // some code
    if (testCondition)
        return; //early return
    // some more code
}
3
mr_T 10 Сен 2014 в 18:53
Вы пробовали добавлять журналы (например, printf или запись в файл) и отлаживать? В коде, который вы показали, будет вызван деструктор.
 – 
John Odom
10 Сен 2014 в 18:55
1
Что вы подразумеваете под ошибкой времени выполнения? Исключения С++? Тогда это сработает. Если ваша программа действительно дает сбой, ошибка seg и т. д., то она не будет работать.
 – 
mkaes
10 Сен 2014 в 18:57
1
Да, деструктор TempStore будет вызываться при возврате функции someFunc(), предполагая "нормальное" выполнение программы (например, без сбоев или ошибок сегментации). Это называется идиомой "Приобретение ресурсов — это инициализация" (RAII) и является краеугольным камнем современного С++.
 – 
In silico
10 Сен 2014 в 19:02
Да, у меня есть, и, кажется, все в порядке. Но поскольку я только начал работать над большим проектом, для которого я еще не знаю всех зависимостей и возможных ошибок и странностей времени выполнения, я надеялся получить некую «синтаксическую гарантию» того, что мой объект будет уничтожен в любом случае.
 – 
mr_T
10 Сен 2014 в 19:03

3 ответа

Лучший ответ

Деструктор автоматического объекта будет вызван, когда программа покинет область видимости объекта. Это включает возврат из функции (ранний или иной) и выход через исключение - до тех пор, пока исключение обрабатывается. В случае исключения он вызывается во время раскрутки стека перед обработкой исключения.

Он может не вызываться в некоторых случаях, в том числе:

  • уходя по телефону longjmp; это дает неопределенное поведение;
  • выход через исключение, которое не обрабатывается; не указано, разматывается ли стек.
  • завершение программы (например, вызов exit или подача сигнала, вызывающего завершение).
6
Mike Seymour 10 Сен 2014 в 19:03

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

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

2
Mankarse 10 Сен 2014 в 19:02
Не подскажете, как мне поступить в таком случае? Что произойдет, если из деструктора будет выброшено исключение?
 – 
mr_T
10 Сен 2014 в 19:11

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

2
Nikita 10 Сен 2014 в 19:06
2
Этот ответ неполный и, следовательно, неправильный. Из заголовка: «Будет ли вызываться деструктор объекта, если функция… вылетает?»
 – 
Konrad Rudolph
10 Сен 2014 в 19:01
1
Я думаю, что он говорит об исключениях, а не о сбоях
 – 
Nikita
10 Сен 2014 в 19:02
Даже для исключений этого не произойдет, если код не выполняется в блоке try.
 – 
juanchopanza
10 Сен 2014 в 19:02
Извините, код запускается в блоке try на более высоком уровне. Я адаптирую название
 – 
mr_T
10 Сен 2014 в 19:07