Функция try блокирует, но не в конструкторах

просто быстрый вопрос. Есть ли разница между

void f(Foo x) try
{
 ...
}
catch(exception& e)
{
 ...
}

и

void f(Foo x)
{
 try { ... }
 catch (exception& e)
 {
 ...
 }
}

?

Если нет, то почему используются блоки try try (в случае списков инициализации для отложенных конструкторов)? Что произойдет, если конструктор копирования Foo выдает исключение, когда x передается в f?

4 ответа

Функциональные блоки try всегда нужны только в конструкторах. Во всех других случаях точно такой же эффект может быть достигнут путем включения всего тела функции в обычный блок try/catch.

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


Некоторые вещи разрешены, потому что было бы труднее их запретить. Предоставление функции попыткам блокировать некоторые, но не все тела функций усложнят грамматику и компиляторы.


Просто заметил интересный момент в этом Dr. Статья Добба (хотя и довольно старая):

... помните, что вы не можете вернуть значение внутри обработчика функции-try-блока. Поэтому нет смысла использовать блок try функции для не-void-функции

и это их пример кода:

int f()
try
{
 ...
}
catch(Error &e)
{
 // oops, can't return int from here!
}

Что на самом деле означает, что блоки try функции слабее, чем "обычные" блоки try, и их использование должно быть обескуражено, кроме как в конструкторах.

(статья с 2000 года, так что было бы хорошо, если бы кто-нибудь прокомментировал, все ли это в текущем стандарте)


Функциональные блоки try были добавлены явно для целей исключения исключений в списках инициализации конструктора.

В вашем примере нет инициализаций конструктора, поэтому между этими двумя формами нет разницы.

licensed under cc by-sa 3.0 with attribution.