Блок-try-функции
Устанавливает обработчик исключений вокруг тела функции.
Содержание |
[править] Синтаксис
Блок-try-функции это одна из альтернативных форм синтаксиса для тела-функции, которая является частью определение функции.
try инициализатор-конструктора (необязательно) составное-выражение последовательность-обработчиков
|
|||||||||
инициализатор-конструктора | — | список инициализаторов элементов, разрешённый только в конструкторах |
составное-выражение | — | заключённая в фигурные скобки последовательность операторов, составляющая тело функции |
последовательность-обработчиков | — | последовательность из одного или нескольких предложений catch |
[править] Объяснение
Блок-try-функции связывает последовательность предложений catch со всем телом функции, а также со списком инициализаторов элементов (если используется в конструкторе). Каждое исключение, брошенное из любого оператора в теле функции, или (для конструкторов) из любого элемента или базового конструктора, или (для деструкторов) из любого элемента или базового деструктора, передаёт управление последовательности-обработчиков так же, как исключение, брошенное в обычном блоке try.
#include <iostream> #include <string> struct S { std::string m; S(const std::string& str, int idx) try : m(str, idx) { std::cout << "S(" << str << ", " << idx << ") построен, m = " << m << '\n'; } catch(const std::exception& e) { std::cout << "S(" << str << ", " << idx << ") потерпел крах: " << e.what() << '\n'; } // здесь неявный "throw;" для конструктора }; int main() { S s1{"ABC", 1}; // не бросает (индекс в пределах допустимого) try { S s2{"ABC", 4}; // бросает (выход за границы) } catch (std::exception& e) { std::cout << "S s2... вызывает исключение: " << e.what() << '\n'; } }
Прежде чем будут введены какие-либо предложения catch блока-try-функции в конструкторе, все полностью сконструированные элементы и базовые классы уже будут уничтожены.
Если блок-try-функции находится в конструкторе делегирования, который вызвал конструктор без делегирования, который завершился успешно, но затем тело конструктора делегирования вызывает исключение, деструктор этого объекта будет завершён до любых предложений catch блока-try-функции. |
(начиная с C++11) |
Прежде чем будут введены какие-либо предложения catch блока-try-функции в деструкторе, все базовые и невариантные элементы уже будут уничтожены.
Поведение не определено, если предложение catch блока-try-функции, используемого в конструкторе или деструкторе, обращается к базовому классу или нестатическому элементу объекта.
Каждое предложение catch в блоке-try-функции для конструктора должно завершаться выдачей исключения. Если управление достигает конца такого обработчика, текущее исключение автоматически выбрасывается снова, как будто через throw;. Оператор return не допускается ни в одном предложении catch блока-try-функции кон��труктора.
Достижение конца предложения catch для блока-try-функции в деструкторе также автоматически повторно выдаёт текущее исключение, как будто с помощью throw;, но допускается оператор return.
Для всех других функций достижение конца предложения catch эквивалентно return;, если возвращаемый тип функции (возможно, cv-квалифицированный) void, иначе поведение не определено.
[править] Примечание
Основная цель блоков-try-функций состоит в том, чтобы реагировать на исключение, созданное из списка инициализаторов элементов в конструкторе, путём регистрации и повторного создания, изменения объекта исключения и повторного создания, создания вместо него другого исключения или завершения программы. Они редко используются с деструкторами или с обычными функциями.
Блок-try-функции не перехватывает исключения, генерируемые конструкторами копирования/перемещения и деструкторами параметров функции, передаваемых по значению: эти исключения генерируются в контексте вызывающего объекта.
Блок-try-функции верхнего уровня потока не перехватывает исключения, генерируемые конструкторами и деструкторами локальных объектов потока (за исключением конструкторов локальных объектов потока в области видимости функции). | (начиная с C++11) |
Аналогично, блок-try-функции main() не перехватывает исключения, генерируемые конструкторами и деструкторами статических объектов (за исключением конструкторов статических локальных объектов функции).
Область видимости и время жизни параметров функции (но не любых объектов, объявленных в самой функции), распространяются до конца последовательности-обработчиков.
int f(int n = 2) try { ++n; // инкрементирует параметр функции throw n; } catch(...) { ++n; // n находится в области видимости и по-прежнему ссылается на параметр функции assert(n == 4); return n; }
[править] Отчёты о дефектах
Следующие изменения поведения были применены с обратной силой к ранее опубликованным стандартам C++:
Номер | Применён | Поведение в стандарте | Корректное поведение |
---|---|---|---|
CWG 1167 | C++98 | не было указано, будет ли блок-try-функции в деструкторе перехватывать исключения из базового деструктора или деструктора-элемента |
такие исключения перехватываются |