очистка после исключения [дубликат]


На этот вопрос уже есть ответ здесь:

У меня есть такой код:

class myclass
{
     myclass()
     {
        // doing some init here
      }
     ~myclass()
     {
        // doing some important clean up here
     }
     void Do()
     {
          //    doing some work which may throw exception
      }
}

И я использую этот класс следующим образом:

MyFunction()
{
    myclass mc;
    mc.do();
 }

Мой вопрос:

Если в функции do есть исключение, что произойдет? Деструктор майкласа называется?

Если нет, как лучше всего справиться с такого рода ситуациями? Предположим, что у меня нет исходного кода, и я уверен в том, что происходит в деструкторе.

3   3   2013-12-05 14:14:09

3 ответа:

Если в функции do есть исключение, что произойдет?

Если у вас есть обработчик, он будет обработан.

Называется ли деструктор myclass?

Да, определенно. Стандарт цитирует это::

Объект любой длительности хранения, инициализация или уничтожение которого завершается исключением будет иметь деструкторы, выполняемые для всех его полностью построенных подобъектов (исключая вариантные члены Союз-как будто класс), то есть для подобъектов, для которых Принципал конструктор (12.6.2) завершил выполнение, а деструктор казнь еще не началась. Аналогично, если не делегирующий конструктор для объекта завершилось выполнение и делегирующий конструктор для этот объект завершается с исключением, деструктор объекта будет вызванный. Если объект был выделен в новом выражении, то совпадение функция освобождения (3.7.4.2, 5.3.4, 12.5), если таковая имеется, вызывается для бесплатно хранилище, занимаемое объектом.

Весь этот процесс известен как "разматывание стека":

Процесс вызова деструкторов для построенных автоматических объектов на пути из блока try, чтобы вбрасывание выражение называется "стек размотка."Если деструктор, вызванный во время разматывания стека, выходит с исключение, std:: terminate вызывается (15.5.1).

C++11 15.5.1 функция std:: terminate () [кроме.прекратить]

2 ... в ситуации, когда соответствующий обработчик не найден, это реализация-определяет, будет ли стек размотан перед запуском. вызывается std:: terminate ().

Если исключение где-то перехвачено, то размотка стека гарантирует, что деструктор вызывается для этого объекта (и, в общем случае, для всех автоматических переменных, которые выходят из области действия в результате исключения). Это очень важная гарантия, без которой мы не могли бы использовать такие методы, как RAII для написания кода, безопасного для исключений.

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

Если программа завершается каким-либо другим способом, например вызовом exit() или terminate(), или получением необработанного сигнала, то стек не будет размотан. Если вы нуждаетесь в чистом разрушении в этих ситуациях, то все станет грязным.

В C++ нет явных предложений" finally", как во многих других языках, но вместо этого вы полагаетесь на" RAII", который по сути является методом использования ограниченных" автоматических " переменных и полагаетесь на то, что их деструктор будет вызван в соответствующий момент, когда они выходят из области видимости.

В вашем случае деструктор myclass будет вызван, даже если mc.do() создает исключение. Во многих из этих проблем с "закрытием" объект, помещенный в верхнюю часть блока scope, является классом, который используется только с целью вызова деструктора по завершении.

Язык "D" имеет специальный синтаксис замыкания. Были попытки написать библиотеки, которые делают это в C++ , и с лямбдами, конечно, легче писать, чем сейчас, чем раньше, хотя я не думаю, что они являются формальной частью C++ до сих пор.