Подтвердить что ты не робот

Разница между синтаксисом try-catch для функции

Недавно я использовал этот синтаксис для try-catch для функции.

struct A
{
  int a;

  A (int i) : a(i)  // normal syntax
  {
    try {}
    catch(...) {}
  }

  A ()   // something different
  try : a(0) {}
  catch(...) {}

  void foo ()  // normal function
  try {}
  catch(...) {}
};

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

4b9b3361

Ответ 1

Первый синтаксис:
Объем блока try начинается после завершения списка инициализации члена, поэтому любое исключение, созданное при инициализации элемента , не будет поймано этим блоком try-catch.

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

Третий синтаксис:
Это гарантирует, что любое исключение, отбрасываемое между стартовой фигурной скобкой блока try внутри тела функции, будет поймано соответствующим образом. Это будет означать, что любое исключение, вызванное при передаче аргумента (если это может произойти), не будет зажато в этом блоке try-catch.

Итак, да, они отличаются друг от друга тем, что они предоставляют.


EDIT:
Некоторые рекомендации следует учитывать при использовании второго синтаксиса (function-try-block) в конструкторах и деструкторах:

В соответствии со стандартом С++,

Если блокирующий блок не бросает (ни регенерирует исходное исключение, ни бросает что-то новое), а элемент управления достигает конца блока catch конструктора или деструктора, тогда исходное исключение автоматически возвращается.

Простыми словами:
Код обработчика конструктора или деструктора функции-try-block ДОЛЖЕН завершить, испустив какое-то исключение.

Руководство 1:
Обработчики функции-try-block конструктора имеют только одну цель - перевести исключение. (И, возможно, делать каротаж или некоторые другие побочные эффекты.) Они не полезны для каких-либо других целей.

Выбрасывание исключения из деструкторов - плохая идея, посмотрите здесь, чтобы узнать почему. Руководство 2:
Функция-try-blocks деструктора практически не используется. Там никогда не должно быть ничего для их обнаружения, и даже если есть что-то обнаружить из-за злого кода, обработчик не очень полезен для чего-либо, потому что он не может подавить исключение.

Руководство 3:
Всегда очищайте неуправляемое получение ресурсов в локальных обработчиках try-блоков внутри тела конструктора или деструктора, никогда не выполняйте обработчики функции-try-block конструктора или деструктора.


Для стандартных поклонников:

Стандарт С++, пункт 15.3, пункт 15:

Если в обработчике функции-try-блока конструктора появляется оператор return, программа плохо сформирована.

Стандарт С++, пункт 15.3, пункт 16:

Исключено обрабатывается исключение, если управление достигает конца обработчика функции-try-блока конструктора или деструктора. В противном случае функция возвращается, когда управление достигает конца обработчика для функции-try-block (6.6.3). Вытекание конца функции-try-block эквивалентно возврату без значения; это приводит к поведению undefined в возвращающей значение функции (6.6.3).


Литература:
Взгляните на этот должен прочитать ресурс здесь для получения более подробной информации и объяснений. p >

Ответ 2

Функция-try-block полезна в основном в конструкторах, потому что другого способа улавливания исключений в списке инициализации нет. В деструкторах нужно быть осторожным, чтобы вернуться в блок catch, потому что исключение будет автоматически повторно выбрано. (И в хорошем дизайне деструкторы не должны бросать.) В обычных функциях эта функция не полезна. Редактировать: старая, но все еще хорошая статья: http://drdobbs.com/184401316

Ответ 3

Можно также привести спецификацию... Или хотя бы проект.

Раздел 15 (4):

Функция-try-блок связывает обработчик-seq с инициализатором ctor, если он присутствует, и составной оператор. Исключение, созданное при выполнении составного оператора или, для конструкторов и деструкторов, во время инициализации или уничтожения, соответственно, субобъектов классов, передает управление обработчику в блок try-try так же, как исключение во время выполнения блока try-block передает управление другим обработчикам.

(Здесь обработчик-seq - это материал после catch, а compound-statement - тело функции.)

Таким образом, "блок try try" в конструкторе или деструкторе ловит исключения, вызванные инициализаторами ctor, а также по конструкции или уничтожению подобъектов.

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

Интересная особенность и новая для меня. Спасибо, что вызвали его.

Ответ 4

Пример "что-то другое" помещает обработку списка инициализаторов в область действия блока try.