Ошибочная обработка: возвращаемое значение по сравнению с исключением в C++

В ходе того, чтобы спрашивать о ловле 'делятся на 0' исключений, я нашел, что с C++, мы не можем сделать этого. Я имею в виду, делюсь на 0, не бросает станд.:: исключение.

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

Я говорю, что это сбивает с толку, поскольку я думал, что C++ принял идею исключения для замены 'старой доброй ошибки отчета о C/UNIX путем возврата метода значения'.

Вот мои вопросы

  • Q1: Почему C++ не бросает станд.:: ошибка исключения для деления 0? Есть ли какая-либо причина позади этого?
  • Q2: Обычно, какая ошибочная обработка замышляет пользователей C++, используют? Всегда бросайте ошибку, и исключением является деление 0 ошибками?
  • Q3: В целом языки ООП предпочитают (или даже осуществите), использование исключения. Это корректно?
7
задан prosseek 25 June 2010 в 03:34
поделиться

7 ответов

C++ предполагает, что вы знаете, что делаете, не платит за то, что вы не просите, и не делает никаких предположений о платформах, для которых он предназначен.

Если вы хотите делить числа, было бы довольно неэффективно требовать от компилятора проверять знаменатель и бросать перед делением. (Мы его об этом не просили.) Так что этот вариант отпадает; мы не можем делать такую проверку при каждом делении, и это особенно расточительно, поскольку большинство делений не на ноль.

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

Единственный вариант - оставить поведение неопределенным. И это именно то, что вы получаете: неопределенное поведение.


Языки ООП могут делать то или иное, но это не имеет значения, поскольку ООП не является четко определенным, а C++ в любом случае не является языком ООП. В общем, используйте наиболее подходящий инструмент. (Исключения - для исключительных ситуаций)

.
9
ответ дан 6 December 2019 в 11:45
поделиться

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

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

C++ не является (только) ОО-языком и не принуждает (в большинстве случаев) к использованию исключений. Он предоставляет их в качестве инструмента для использования там, где это необходимо. Есть и другие языки, которые принуждают к использованию исключений в гораздо большей степени.

2
ответ дан 6 December 2019 в 11:45
поделиться

1) Выбрасывание исключений - это дорогая операция. Философия C++ заключается в том, чтобы не платить за то, что вы не используете. Если вам нужны исключения, бросайте их сами (или используйте библиотеки, которые это делают).

2) Никогда не принимайте ошибку деления на ноль. Это зависит от ситуации, если вы знаете, что на входе никогда не будет 0, никогда не проверяйте ее. Если вы не уверены, всегда проверяйте. Затем либо выбросьте исключение, либо спокойно проглотите ошибку. Это зависит от вас.

3) Бросание исключений, особенно в сочетании с RAII, может сделать код по-настоящему элегантным и красивым. Это может быть приемлемо не во всех ситуациях. Вы можете быть на 100% уверены в своих исходных данных и желать сырой производительности. Если вы создаете DLL, вам не очень хочется выбрасывать исключения из вашего api, но для критически устойчивой статически связанной библиотеки можно посоветовать это сделать.

2
ответ дан 6 December 2019 в 11:45
поделиться

C ++ не использует много полезных принципы в некоторых местах, чтобы поддерживать совместимость с кодом C. Java и тому подобное не имеет таких ограничений, поэтому они могут делать то, что хотят.

В C ++ всегда генерировать исключение. Но для чего-то вроде деления на ноль вам действительно стоит просто проверить это самостоятельно. Это не исключительное обстоятельство, это вы не можете себя контролировать.

1
ответ дан 6 December 2019 в 11:45
поделиться

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

1
ответ дан 6 December 2019 в 11:45
поделиться

Насчет Q3 - исключения это то, что должно происходить исключительно :) Так что избегать (что возможно с div0) всегда лучше. В дополнение к словам Emyr (который прав насчет "избегания траты циклов на вычисления") вы должны учитывать, что выброс исключения означает много "внутренней работы", поскольку контекст меняется (вы можете оставить цикл, функции, методы экземпляра....) и ваш "стек исключений" должен быть подготовлен.

Так что в целом обработка исключений - это "общий метод" для обработки исключений. Но это не должно быть шаблоном для избегания "проверки значений".

if(!string.IsNullOrEmpty(....) ... намного лучше, чем try{ xx=MyMabeNullString.Length... } catch{ //errmess - я мог бы проверить это раньше :) }

1
ответ дан 6 December 2019 в 11:45
поделиться
  1. Поскольку C ++ предназначен для использования «близко к металлу» и в основном пытается передавать простые операции, такие как разделение, на оборудование относительно напрямую (так что, если вы не можете полагаться на оборудование для обеспечения соблюдения ограничений, C ++, вероятно, не будет по умолчанию тоже).
  2. Я не думаю, что есть универсальный ответ на этот вопрос. Некоторые программисты на C ++ пишут код, похожий на C, в котором почти никогда не используется обработка исключений. Другие используют обработку исключений довольно строго (и большинство из них находится где-то посередине).
  3. Хотя почти наверняка существует корреляция между объектно-ориентированным запуском и обработкой исключений, я не думаю, что это действительно причина и следствие. Факторы, которые мне кажутся вероятными:
    1. ООП и обработка исключений, как правило, наиболее полезны в похожих (например, больших) проектах.
    2. И ООП, и обработка исключений со временем стали более распространенными. В старых объектно-ориентированных языках часто отсутствует обработка исключений. В новых языках часто есть обработка исключений, даже если они вообще не объектно-ориентированные.
1
ответ дан 6 December 2019 в 11:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: