глядя на код, на который я наткнулся:
throw /*-->*/new std::exception ("//...
и я всегда думал, что тебе здесь не нужно / не стоит использовать new
.
Как правильно, оба в порядке, если да, есть ли разница?
Кстати, из того, что я вижу, когда "grepping" с помощью PowerShell boost libs никогда не использовал throw new
.
PS также я нашел некоторый код CLI, который использует throw gcnew
. Это нормально?
throw gcnew
было бы полезно, например. если вы хотите, чтобы управляемый код перехватил ваше исключение. Может кто-нибудь поправить меня в этом?System::Exception
обычно является ссылкой на управляемый объект в куче со сборкой мусора. Я всегда бросалgcnew
и ловилSystem::Exception ^
. Конечно, я также постоянно используюfinally
C ++ / CLI, хотя не часто смешиваю с исключениями C ++ в одномtry
блоке, я не уверен, почему.Ответы:
Обычный способ генерировать и перехватывать исключения - это генерировать объект исключения и перехватывать его по ссылке (обычно по
const
ссылке). Язык C ++ требует, чтобы компилятор сгенерировал соответствующий код для создания объекта исключения и должным образом очистил его в подходящее время.Создание указателя на динамически выделяемый объект - не лучшая идея. Предполагается, что исключения позволят вам написать более надежный код перед лицом ошибок. Если вы выбрасываете объект исключения обычным способом, вы можете быть уверены, что независимо от того, будет ли он пойман предложением catch с указанием правильного типа с помощью a
catch (...)
, будет ли он затем повторно брошен или нет, он будет правильно уничтожен в соответствующее время. (Единственное исключение - ситуация, когда она вообще не обнаруживается, но это неустранимая ситуация, как бы вы на нее ни смотрели.)Если вы бросаете указатель на динамически выделяемый объект, вы должны быть уверены, что независимо от того, как выглядит стек вызовов в момент, когда вы хотите выбросить свое исключение, есть блок catch, который называет правильный тип указателя и имеет соответствующий
delete
вызов. Ваше исключение никогда не должно быть перехвачено,catch (...)
если этот блок повторно не генерирует исключение, которое затем перехватывается другим блоком catch, который правильно обрабатывает исключение.Фактически это означает, что вы взяли на вооружение функцию обработки исключений, которая должна упростить написание надежного кода, и очень затруднила написание кода, правильного во всех ситуациях. Это оставляет в стороне проблему, заключающуюся в том, что будет практически невозможно действовать как код библиотеки для клиентского кода, который не будет ожидать этой функции.
источник
Нет необходимости использовать
new
при выдаче исключения.Просто пиши:
и поймать как:
Обратите внимание, что это
yourexception
должно происходитьstd::exception
прямо или косвенно.источник
new
? почему происходятyourexception
изstd::exception
?throw std::exception;
работает? g ++, похоже, не скомпилирует его ...std::exception
это тип, и вы не можете выбросить тип , вы должны выбросить объект . Итак, синтаксис должен быть таким: онthrow std::exception();
будет компилироваться. Насколько это хорошо - это совсем другой вопрос.Бросок
new std::exception
является правильным, если сайт вызова ожидает пойматьstd::exception*
. Но никто не рассчитывает поймать указатель на исключение. Даже если вы документируете, что делает ваша функция, и люди читают документацию, они все равно могут забыть иstd::exception
вместо этого попытаться поймать ссылку на объект.источник
new std::exception
является правильным только в том случае, если сайт вызова ожидает поймать указатель И ожидает взять на себя управление исключением выделения И никогда не будет случаев, когда ваша функция будет вызываться чем-то, что явно не улавливает правильный указатель (catch(...)
или без обработки), иначе произойдет утечка объекта. Короче говоря, это можно приблизительно выразить как «никогда».В C ++ FAQ есть хорошее обсуждение этого:
В основном, «если нет веской причины не ловить по ссылке. Избегайте перехвата по значению, поскольку это приводит к созданию копии, и копия может иметь другое поведение, чем то, что было выброшено. Только в очень особых обстоятельствах вы можете ловить по указателю. "
источник
A
отличается от типа,A*
поэтому, если я это сделаю,throw A()
я НЕ смогу пойматьcatch(A* e)
его, потому что это совершенно другой тип.Оператор new не может гарантировать, что он никогда не вызовет исключения. По этой причине использование его для выдачи «действительного» (предполагаемого) исключения приведет к созданию кода, который не может гарантировать сбой. Поскольку единовременно может быть только одно исключение, и ваша программа пытается сгенерировать два, прежде чем какое-либо из них может быть обнаружено, лучшее, что может сделать реализация, - это немедленно прервать вашу программу, например, вызвав std :: terminate.
источник