Должна ли быть исключение функция, которая может завершиться ошибкой только из-за переполнения целых чисел? - PullRequest
3 голосов
/ 26 апреля 2020

Полный вопрос соответствует названию. Вот краткий пример:

constexpr int increment(int const value) /*noexcept?*/ {
  return value + 1;
}

Насколько я знаю, noexcept следует интерпретировать как "nofail" при принятии решения о том, отмечать функцию или нет. Следовательно, никакая возможная ситуация для throw не является единственной причиной, которую необходимо учитывать.

Я не использую C ++ 20, поэтому мои переполнения со знаком еще не определены. :)

Ответы [ 2 ]

4 голосов
/ 26 апреля 2020

Насколько я знаю, ничто, кроме как не должно интерпретироваться как "nofail"

Это не правильно. noexcept буквально означает «я обещаю, что эта функция никогда не выдаст исключение». Есть множество других типов сбоев, таких как ошибки сегментации, недопустимые инструкции, вызов чисто виртуальных функций, целочисленное деление на ноль, не говоря уже о том, что «Боб в бухгалтерии сказал мне, что все наши номера клиентов состоят только из цифр, но я только что нашел Нашим самым первым идентификатором клиента был фактически Q001, и он не анализируется ". Ни один из них не обязательно приведет к исключению, и ни одно из них не будет переполнено целыми числами со знаком, поэтому при сбое функций таким способом все равно может быть noexcept, даже если они могут потерпеть неудачу - они просто не могут генерировать исключения C ++.

Затем вы можете задаться вопросом: «Что произойдет, если функция noexcept сгенерирует исключение?» В этом случае будет вызван std::terminate(), и ваша программа завершится.

2 голосов
/ 26 апреля 2020

noexcept - это просто ваше «обещание», что функция никогда не допустит выхода из нее исключения, а смысл в том, что если это произойдет, ваш код остановится прямо здесь, вызвав std::terminate вместо того, чтобы разрешить исключение escape.

Знание того, что функция никогда не сгенерирует исключение, позволяет компилятору генерировать более эффективный / компактный код в вызывающей программе и позволяет создавать более надежное программное обеспечение (программное обеспечение, которое немедленно завершается, когда что-то не было разработано обрабатывать случившееся более надежно, чем программное обеспечение, которое вместо этого продолжает делать случайные вещи ... это то, о чем многие молодые программисты не понимают).

Исключения, к сожалению, не являются единственным источником сбоев в C ++, где вы иметь большого слона в комнате «неопределенного поведения», поэтому написание действительно надежного программного обеспечения на C ++ является чрезвычайно трудной задачей, потому что вы также должны избегать любого потенциально неопределенного поведения (а это почти невозможно сделать; например, может генерировать неопределенное поведение, любую целочисленную математическую операцию, любое использование итераторов, любой доступ к массиву, любой доступ к указателю, любую неинициализированную переменную, любой многократный неупорядоченный побочный эффект в одной и той же памяти, любое состояние гонки ... et c. et c.).

Обратите внимание, конечно, что даже совершенно «безопасный» низкоуровневый язык, который не имеет неопределенного поведения, но гарантирует гарантированные ошибки времени выполнения, не будет «серебряной пулей» для написания действительно надежного программного обеспечения. Причина в том, что вы можете иметь своего рода «неопределенное поведение» на более логичном уровне, если ваши алгоритмы не работают так, как вы хотели, во всех случаях, которые им представлены.

Другими словами, не так много разница для конечного пользователя, если ваша программа делает случайные вещи из-за неопределенного поведения C ++ или из-за того, что вы поймали и обработали исключение, которое не было источником, откуда вы думали, что оно исходит (от чего nothrow хочет вас защитить) или потому, что ваш код просто не учел и учел, что контактные данные клиента могут иметь и пустой номер телефона.

Неопределенная концепция поведения, конечно, плоха и существует потому, что позволяет генерировать более быстрый код. На мой взгляд, это спорно, это должно быть по умолчанию на языке программирования; другие языки предпочитают более безопасную среду по умолчанию и вместо этого допускают специально помеченные «быстрые и опасные» зоны, где требуется, чтобы программист никогда не делал ошибок низкого уровня.

...