поймать исключение указателем в C ++ - PullRequest
47 голосов
/ 07 января 2010

Я обнаружил, что есть три способа отловить исключение, в чем различия?

1) вылов по стоимости;

2) вылов по ссылке;

3) поймать по указателю;

Я только знаю, что catch by value вызовет две копии объекта, catch by reference - одну. Так как насчет поймать по указателю? Когда использовать catch по указателю? В дополнение к метанию объекта, могу ли я бросить указатель на такой объект?

class A {}

void f() {

  A *p = new A();
        throw p;


}

Ответы [ 5 ]

77 голосов
/ 07 января 2010

Рекомендованный способ - бросить по значению и поймать по ссылке .

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

Если вы действительно чувствуете, что должны бросить указатель, используйте умный указатель, такой как shared_ptr.

Во всяком случае, Херб Саттер и Алексей Александреску очень хорошо объясняют это в своей книге по стандартам кодирования C ++, которую я перефразировал.

См. Стандарты кодирования C ++: «бросить по значению», «поймать по ссылке» .

16 голосов
/ 07 января 2010

Catch следует обычным правилам совместимости присваивания, то есть, если вы бросаете значение, вы можете перехватить его как значение или ссылку, но не как указатель;если вы бросаете указатель, вы можете поймать его только как указатель (или ссылку на указатель ...).

Но на самом деле не имеет смысла бросать указатели, это вызовет только головную боль при управлении памятью,Таким образом, вы должны, в общем, следовать правилу бросок по значению, ловить по ссылке , как объяснил Грегори.

4 голосов
/ 07 января 2010

Microsoft MFC использует catch by pointer, но я думаю, что это было для совместимости с компилятором, прежде чем try и catch были правильно реализованы; первоначально они использовали макросы TRY и CATCH для имитации этого. Каждое исключение происходит от CException, у которого есть метод определения необходимости удаления объекта.

Я не рекомендовал бы это для любого современного дизайна исключения. Поймать по ссылке это путь.

2 голосов
/ 07 января 2010

Хотя можно бросать практически любой объект любого типа, при этом мало что можно получить (если вообще что-то).Динамическое распределение полезно в первую очередь, когда объект должен иметь время жизни, не подходящее для автоматического размещения, то есть вы хотите, чтобы его время жизни не зависело от обычной области действия программы.Это не имеет особого смысла.Объект исключения обычно используется только внутри обработчика исключений, и вы явно хотите, чтобы он был уничтожен при выходе из (последнего) обработчика этого исключения.

Существует также тот факт, что вы обычно хотите сохранить исключениеобработка кода довольно проста.Например, если вы пытаетесь сообщить об исчерпании или повреждении свободного хранилища / кучи, попытка выделить объект исключения из этого исчерпанного / поврежденного свободного хранилища / кучи обычно не будет работать очень хорошо ...

1 голос
/ 07 января 2010

Не очень хороший сценарий для ловли / выдачи исключения по указателю. Семантика C ++ допускает это, но это не очень полезно, поскольку большую часть времени вы будете вызывать временное исключение или строковый объект.

Однако некоторые библиотеки (я думаю, Boost.Graph делает это) используют throw для передачи возвращаемого значения вызывающей стороне из глубоко рекурсивной функции; в такой ситуации возвращаемое значение может быть указателем, поэтому выбрасывание указателя имеет смысл.

...