Устаревший список бросков в C ++ 11

Как я вижу в cppreference, Классические списки объявлений throw теперь устарели в C ++ 11. Какова причина выхода из этого механизма, и как я должен указать, какие исключения вызывает мою функцию?

40

Решение

Для более подробного объяснения см .: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3051.html

Как указано в комментарии национального органа выше, спецификации исключений не оказались полезными на практике. Существует множество обсуждений проблем со спецификациями исключений в C ++ (см., Например, [Sutter02], [Boost03]), но основными проблемами являются:

  • Проверка во время выполнения: спецификации исключений C ++ проверяются во время выполнения, а не во время компиляции, поэтому они не дают программисту гарантий того, что все исключения были обработаны. Режим сбоя во время выполнения (вызов std :: surprise ()) не поддается восстановлению.
  • Затраты времени выполнения: проверка времени выполнения требует, чтобы компилятор генерировал дополнительный код, который также препятствует оптимизации.
  • Неприменимо в универсальном коде: в универсальном коде, как правило, невозможно узнать, какие типы исключений могут быть вызваны операциями над аргументами шаблона, поэтому точная спецификация исключений не может быть написана.

На практике полезны только две формы гарантий создания исключений: операция может выдать исключение (любое исключение) или операция никогда не вызовет исключение. Первое выражается посредством полного исключения спецификации исключения, а второе может быть выражено как throw (), но редко из-за соображений производительности.

[N3050] вводит новый тип спецификации исключений, noexcept, указывает, что функция не будет генерировать никаких исключений. В отличие от throw (), noexcept не требует, чтобы компилятор вводил код для проверки, генерируется ли исключение. Скорее, если функция, указанная как noexcept, завершается через исключение, результатом является вызов std :: terminate ().

С введением noexcept теперь программисты могут выражать два вида исключительных гарантий, которые полезны на практике, без дополнительных накладных расходов. Поэтому в этой статье предлагается отказаться от спецификаций «динамических» исключений, то есть тех, которые записываются как throw (type-id-listopt).

44

Другие решения

Ответ Питера не затрагивает актуальную проблему спецификаций исключений для разработчика и пользователя:

  • Спецификации исключений приводят к завершению программы (или, точнее, к обработчикам завершения вызовов), если разработчику не удалось сохранить гарантию на выброс только определенных исключений.
  • Таким образом, вызывая метод со спецификацией исключения, вы, как пользователь библиотеки, создаете свой собственный код Больше склонен к полному отказу / прекращению. Если библиотечная функция запускается нехватка памяти (std :: bad_alloc), у вас не будет возможности ее перехватить, но вместо этого вы будете прерваны.
  • Таким образом, первоначальная цель — сообщить наиболее вероятные варианты сбоев и попросить вас, как пользователя, обработать их — не была достигнута.
  • Как разработчик на другой стороне, вы не можете больше вызывать любые другие методы, которые не имеют спецификаций исключений, потому что они могут привести к прекращению ваших вызывающих. Страшное место, чтобы быть в.

Вывод заключается в том, что C ++ должен был пойти тем же путем, что и Java:

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

Noexcept (начиная с C ++ 11) страдает той же концептуальной ошибкой, так как это также вызовет завершение во время выполнения, если спецификация тоже не соблюдается, то есть метод выбрасывает, который был объявлен как not. Это делает noexcept невозможно использовать для чего-либо серьезного, но в большинстве случаев (на ум приходят конструкторы).

7

Они производят медленный и больший код, потому что libc ++ должен проверить, нарушает ли какое-либо исключение, распространяющееся из функции, его спецификацию исключения и вызов std::unexpected, Это вряд ли когда-либо полезно и хуже, чем просто документирование исключений, которые выдает сама функция.

4

Только форма без списка бросить () устарела. Формы без пропущенного списка бросить (int, исключение&), и т.д. не являются устаревшими.

-2
По вопросам рекламы [email protected]