«Мы не используем исключения C ++» - какая альтернатива?Позвольте этому разбиться? - PullRequest
32 голосов
/ 16 августа 2010

«Мы не используем исключения C ++.»

Если вы не используете исключения, что происходит при возникновении ошибки? Вы только что допустили сбой программы?

Ответы [ 7 ]

27 голосов
/ 16 августа 2010

Или вы могли бы прочитать немного дальше:

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

Учитывая, что существующий код Google не допускает исключений, затраты на использование исключенийнесколько больше, чем затраты в новом проекте.Процесс преобразования будет медленным и подверженным ошибкам.Мы не считаем, что имеющиеся альтернативы исключениям, такие как коды ошибок и утверждения, представляют собой значительное бремя.

Наш совет против использования исключений основан не на философских или моральных соображениях, а на практических.Поскольку мы хотели бы использовать наши проекты с открытым исходным кодом в Google, и это трудно сделать, если в этих проектах используются исключения, мы должны также рекомендовать избегать исключений в проектах с открытым исходным кодом Google.Вероятно, все было бы иначе, если бы нам пришлось делать все заново с нуля.

Существует исключение из этого правила (без каламбура) для кода Windows.

24 голосов
/ 16 августа 2010

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

10 голосов
/ 04 января 2015

Альтернативы исключениям, отличным от кодов возврата:

  • Условный обработчик в стиле LISP.
  • Программные сигналы и слоты в стиле QT.
  • Аппаратное прерывание или обработчик сигнала без стека раскручивается.Это раскрутка стека, это проблема исключений на встроенных устройствах.
  • longjmp / setjmp
  • Функция обратного вызова
  • Значение флага, например errorno (Unix), GetLastError (Windows), glGetError (OpenGL) и т. Д.
  • Сообщениеочередь, если программа управляется событиями
  • Изменяемый функтор.Объект обработчика как параметр ввода-вывода, указатель изменяется при ошибке.
  • Волокна или нити с подпрограммой разрешения ошибок
  • asm __int 3 или эквивалентный процессору
  • Наложениеинструкции или функции батута.

... и многое другое.Многие из перечисленного являются дружественными для встроенных устройств.

7 голосов
/ 16 августа 2010

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

Это «Мы не используем исключения C ++», а не «Мы не перехватываем исключения C ++».

6 голосов
/ 16 августа 2010

Справочник по стилю объясняет это хорошо:

На их лице преимущества использования исключения перевешивают затраты, особенно в новых проектах. Тем не мение, для существующего кода, введение исключения имеют последствия для всех зависимый код. Если исключения могут быть распространяется за пределы нового проекта, это также становится проблематичным для интеграции новый проект в существующий Код без исключений. Потому что большинство существующий код C ++ в Google не готовы иметь дело с исключениями, это сравнительно сложно принять новый код, генерирующий исключения.

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

5 голосов
/ 16 августа 2010

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

Как и во многих существующих документах с ответами, вы можете вернуть дозорное значение (например, истинное / ложное значение успеха, перечисление). Эта практика широко знакома по обычным функциям C, указанным в POSIX и libc, таким как fopen (), strstr () или printf ().

Другим важным вариантом является установка некоторого внутреннего состояния, к которому они могут обращаться позже. Почему вы можете или хотите сделать последнее? Потому что некоторые функции, особенно конструкторы и операторы C ++, обычно не дают вам возможности вернуть код ошибки. Например, в:

  X x1(something), x2(whatever);
  fn(x1 + x2);

X::X(...) не может ничего вернуть. X::operator+ может быть вызвано (при условии, что + не вызывается по результатам операторов преобразования), но fn(), вероятно, ожидает const X& (или X&& с C ++ 11), и operator+ необходимо вернуть X, чтобы он работал в успешной ситуации. У вас нет шансов вернуть отдельный тип кода ошибки. class X может потребоваться установить какое-то внутреннее состояние, которое другой код (возможно, fn(), возможно, оператор после fn() вызывается) проверяет, чтобы предпринять соответствующее действие.

Итак, вы получите что-то вроде:

X x1(something), x2(whatever);
assert(x1.is_valid() and x2.is_valid());
X x3 = x1 + x2;
assert(x3.is_valid());
fn(x3);

Обратите внимание, что это соглашение об обработке ошибок является многословным и может игнорироваться или игнорироваться клиентскими кодировщиками - одна из причин исключения была создана. Интересный вариант этого используется большинством аппаратных средств с плавающей запятой - некоторые операции, такие как деление на 0 или недополнение / переполнение, могут устанавливать регистр на значения дозорного типа, такие как Not a Number "NaN" или +/- Infinity, а затем операции, включающие аргумент в таком состоянии размножают состояние до их результата. Например, x = 8 + y / 0; z = x + 2; также установит z для дозорного. Идея заключается в том, что вы можете написать код, который вычисляет правильный результат, когда это возможно, и проверить один раз, прежде чем использовать результат, чтобы увидеть, если ошибка из любого места в коде вычисления аннулирует этот результат. Иногда это работает нормально для математического кода, особенно когда вы не принимаете решения о ветвлении на основе текущих значений переменных, но, к сожалению, во многих ситуациях вы либо не сможете, либо не захотите сделать всех пользователей потенциально недействительный объектный код для защиты и распространения состояний ошибки.

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

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

3 голосов
/ 16 августа 2010

Вы используете версии функций, возвращающие код ошибки, и действуете в соответствии с возвращаемым значением.

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