Подтвердить что ты не робот

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

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

4b9b3361

Ответ 1

Для более подробных рассуждений см.: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3051.html

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

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

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

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

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

Ответ 2

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

Ответ 3

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

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

Вывод состоит в том, что С++ должен был просто пойти так, как это сделала Java:

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

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

Ответ 4

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