Обработка ошибок: возвращаемое значение против исключения в C ++ - PullRequest
7 голосов
/ 25 июня 2010

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

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

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

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

  • В1: Почему C ++ не выдает ошибку std :: exception для деления на 0? Есть ли причина этого?
  • Q2: Какую схему обработки ошибок обычно используют пользователи C ++? Всегда выдает ошибку, а исключением является ошибка деления на 0?
  • В3. В целом языки ООП предпочитают (или даже применяют) использование исключений. Это правильно?

Ответы [ 7 ]

9 голосов
/ 25 июня 2010

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

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

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

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


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

2 голосов
/ 25 июня 2010

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

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

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

2 голосов
/ 25 июня 2010

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

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

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

1 голос
/ 25 июня 2010
  1. Поскольку C ++ предназначен для "близости к металлу" и в основном пытается передавать простые операции, такие как деление, на аппаратное обеспечение относительно напрямую (поэтому, если вы не можете зависеть от аппаратного обеспечения для наложения ограничения, C ++, вероятно,по умолчанию тоже не будет).
  2. Не думаю, что есть универсальный ответ на это.Некоторые программисты на C ++ пишут почти C-подобный код, который почти никогда не использует обработку исключений.Другие используют обработку исключений довольно строго (и большинство находятся где-то посередине).
  3. Хотя почти наверняка существует корреляция между ОО и обработкой исключений, я не думаю, что это действительно причина и следствие.Факторы, которые мне кажутся вероятными:
    1. ООП и обработка исключений, как правило, наиболее полезны в подобных (например, крупных) проектах.
    2. ООП и обработка исключений с течением времени стали более распространенными,В старых ОО-языках часто отсутствует обработка исключений.Более новые языки часто имеют обработку исключений, даже если они вообще не OO.
1 голос
/ 25 июня 2010

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

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

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

1 голос
/ 25 июня 2010

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

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

1 голос
/ 25 июня 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...