Как обнаружить разматывание стека в деструкторе - PullRequest
6 голосов
/ 26 октября 2010

У меня есть простой объект C ++, который я создаю в начале функции F (), чтобы гарантировать, что две совпадающие функции (OpDo, OpUndo) вызываются при запуске и возвращении F (), используя конструктор объекта и деструктор , Однако я не хочу, чтобы операция была отменена, если в теле F () было сгенерировано исключение. Можно ли это сделать чисто? Я прочитал о std :: uncaught-исключение , но его использование не рекомендуется.

Ответы [ 3 ]

6 голосов
/ 26 октября 2010

Большинство людей использовали std::uncaught_exception(), чтобы попытаться определить, ожидает ли исключение исключение, поэтому они могут вызвать исключение из деструктора, если его еще нет.Обычно это считается плохой идеей.

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

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

0 голосов
/ 17 апреля 2011

Вы можете уничтожить идиому Scope Guard .Вместо того, чтобы не делать что-то в деструкторе, когда не генерируется исключение, мы инвертируем это и только делают что-то, если не генерируется исключение:генерируется исключение, do_undo.no_exception() никогда не будет вызываться и, следовательно, никогда не будет устанавливать значение noexcept_ в значение true.:) Пример можно найти здесь на Ideone .

0 голосов
/ 26 октября 2010

Предположим, что ваш F возвращает некоторый класс Helper:

Helper F()
{
     MyClass doUndoWrapper;
}

Когда поток нормальный - хелпер создан. При возникновении исключения копия Helper не создается. Попробуйте использовать эту семантику, поместив в приватный регион конструктор Helper и объявив F другом, чтобы никто не мог создать помощника.

class Helper
{
private:
    friend Helper F();
    Helper(){ //place there OpDo semantic - first entry 
              // construct this class
    Helper(const Helper& copy){ //this must present to allow stack operations
              // copy constructor will be called at end of `F` to return value
              // so place OpUndo semantic there to mark success without exception
...