Throw new std:: exception vs throw std:: exception

глядя на некоторый код, на который я наткнулся:

throw /*-->*/new std::exception ("//...

и я всегда думал, что вам не нужно/вы не должны использовать new здесь.
Каков правильный способ, оба в порядке, если это так, то есть разница?

Кстати, из того, что я вижу, пока "grepping" с PowerShell boost libs никогда не использует throw new.

P.S. также я нашел код CLI, который использует throw gcnew. Это нормально?

Ответ 1

Обычный способ исключения и исключения исключений - это выброс объекта исключения и его привязка по ссылке (обычно const ссылка). Язык С++ требует, чтобы компилятор сгенерировал соответствующий код для создания объекта исключения и правильно очистил его в соответствующее время.

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

Если вы бросаете указатель на динамически выделенный объект, вы должны быть уверены, что независимо от того, какой стек вызовов выглядит в точке, в которой вы хотите создать исключение, есть блок catch, который называет правильный тип указателя и имеет соответствующий delete вызов. Ваше исключение никогда не должно быть поймано catch (...), если только этот блок не повторяет исключение, которое затем поймано, является еще одним блоком catch, который корректно обрабатывает исключение.

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

Ответ 2

Не нужно использовать new при бросании исключения.

Просто напишите:

throw yourexception(yourmessage);

и поймать как:

catch(yourexception const & e)
{
      //your code (probably logging related code)
}

Обратите внимание, что yourexception следует выводить из std::exception прямо или косвенно.

Ответ 3

Бросок new std::exception верен, если сайт вызова ожидает catch std::exception*. Но никто не ожидает, что поймает указатель на исключение. Даже если вы задокументируете, что делает ваша функция, и люди читают документацию, они все равно могут забыть и попытаться поймать ссылку на объект std::exception.

Ответ 4

Часто задаваемые вопросы по С++:

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