Ответ 1
С++ 11 §15.1/8:
" Выражение-выражение без операндов вызывает свернутое в настоящее время исключение (15.3). Исключение составляет возобновляется с существующим временным; не создается новый объект временного исключения.
У меня есть функция foo
, которая может генерировать исключение bar
.
В другой функции я вызываю foo
, но у меня есть возможность добавить некоторые подробности в исключение bar
, если оно было выбрано. (Я бы предпочел не передавать такую информацию, как параметр, в foo
, поскольку она действительно не существует из-за общего характера этой функции.)
Итак, я делаю это в вызывающем:
try {
foo();
} catch (bar& ex){
ex.addSomeMoreInformation(...);
throw;
}
Будет ли throw
перебросить измененное исключение или мне нужно использовать throw ex;
? Последний предположительно возьмет ценную копию, поэтому я бы предпочел не делать этого. Может ли throw
взять копию значения? Я подозреваю, что это не так.
(Я знаю, что могу проверить, но я заинтересован в том, чтобы наткнуться на неуказанную конструкцию или undefined, поэтому хотел бы знать наверняка).
С++ 11 §15.1/8:
" Выражение-выражение без операндов вызывает свернутое в настоящее время исключение (15.3). Исключение составляет возобновляется с существующим временным; не создается новый объект временного исключения.
Собственно, стандарт здесь очень точный. [Except.handle]/17:
Когда обработчик объявляет ссылку на непостоянный объект, любой изменения объекта ссылки являются изменениями во временном объекте инициализируется, когда выполняется выражение throw-expression и будет эффект должен быть отвергнут.
И [except.throw]/8:
Выражение-выражение без операндов возвращает текущую обработку исключение (15.3).
throw
(без объекта исключения) восстановит текущее исключение. (должен быть внутри блока catch, иначе std:: terminate вызывается). Поскольку вы изменили ссылку на текущий объект исключения, вам не нужно явно пытаться выкинуть объект, а бросить повторное бросить измененное исключение и не создавать новый временный объект.
В этом случае вы должны использовать throw
для получения желаемого поведения... i.e throw выбрасывает измененное исключение, поскольку исключение было обнаружено по ссылке.
Позвольте мне попытаться сделать разницу между этими явно выраженными примерами: -
class exception
{
};
class MyException : public exception
{
};
void func()
{
try
{
throw MyException();
}
catch( exception& e )
{
//do some modification.
throw; //Statement_1
throw e; //Statement_2
}
}
Statment_1: -
Что делает бросок, он просто перебрасывает то, что представляет собой текущее исключение, то есть оно не делает дополнительных копий (как это делалось, когда изначально было выбрано исключение). Поэтому, если вы внесете какие-либо изменения в обнаруженное исключение здесь... оно также будет присутствовать в процедуре вызывающего абонента.
Statement_2: -
Это бросает "исключение", которое было первоначально обнаружено как "MyException", так как оно сделает копию снова. Итак, просто забудьте об изменениях, которые вы сделали, они даже не пройдут или исключают исключение для вызывающего. Он выдает "исключение" в процедуру вызова.
Надеюсь, что я понятен (и ПРАВО НА СЛЕДУЮЩИЙ СТАНДАРТ C++) достаточно...
в соответствии с this, исключение исключений из С++ может быть выполнено двумя способами:
Итак, чтобы подчеркнуть мой ответ, throw должен быть в порядке.