Блок-try-функции
Устанавливает обработчик исключений вокруг тела функции.
Содержание |
[править]Синтаксис
Блок-try-функции это одна из альтернативных форм синтаксиса для тела-функции, которая является частью определение функции.
try инициализатор-конструктора (необязательно)составное-выражениепоследовательность-обработчиков | |||||||||
инициализатор-конструктора | — | список инициализаторов элементов, разрешённый только в конструкторах |
составное-выражение | — | заключённая в фигурные скобки последовательность операторов, составляющая тело функции |
последовательность-обработчиков | — | последовательность из одного или нескольких предложений catch |
[править]Объяснение
Блок-try-функции связывает последовательность предложений catch со всем телом функции, а также со списком инициализаторов элементов (если используется в конструкторе). Каждое исключение, брошенное из любого оператора в теле функции, или (для конструкторов) из любого элемента или базового конструктора, или (для деструкторов) из любого элемента или базового деструктора, передаёт управление последовательности-обработчиков так же, как исключение, брошенное в обычном блоке try.
#include <iostream>#include <string> struct S {std::string m; S(conststd::string& str, int idx)try: m(str, idx){std::cout<<"S("<< str <<", "<< idx <<") построен, m = "<< m <<'\n';}catch(conststd::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-функции в деструкторе перехватывать исключения из базового деструктора или деструктора-элемента | такие исключения перехватываются |