2013-08-13 6 views
30

Я знаю, что static_assert делает утверждения во время компиляции и assert - во время выполнения, но в чем разница на практике? Насколько я понимаю, в глубине души они куски кода, какВ чем разница между assert и static_assert?

if (condition == false) exit(); 
  • Может кто-то дать мне пример, где толькоstatic_assert будет работать, или толькоassert?
  • Делают ли они что-либо простое заявление if не могут сделать?
  • Неплохая практика их использования?
+0

'static_assert' - это декларация, встроенная в основной язык. Это не распространяется ни на что, потому что, если это не удается, компиляция прекращается. – jrok

+4

@ KerrekSB Я спросил ** три ** ясных вопроса, пожалуйста, уделите время, чтобы прочитать их, прежде чем делать предположение. – Oleksiy

+1

Вы используете assert, чтобы указать, что в вашей логике программирования есть ошибка, и что она должна быть исправлена ​​в коде. 'if' используется для разветвления между различными логическими путями в коде. Это большая разница – Default

ответ

35

Вы задаете три вопроса, поэтому я постараюсь ответить на каждый из них.

  • Может кто-нибудь дать мне пример того, где толькоstatic_assert будет работать, или толькоassert?

static_assert подходит для тестирования логики в вашем коде во время компиляции. assert хорош для проверки случая во время выполнения, который, как вы ожидаете, всегда должен иметь один результат, но, возможно, каким-то образом может привести к неожиданному результату при непредвиденных обстоятельствах.Например, вы должны использовать только assert для определения того, прошел ли указатель, переданный в метод, null, когда кажется, что этого никогда не должно происходить. static_assert не поймал бы это.

  • Они делают что-либо простое заявление if не могут сделать?

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

  • Это плохая практика, чтобы использовать их?

Совсем нет!

+0

Хороший ответ, однако, добавление, что assert (вариант исполнения) работает только в отладочных сборках и является noop в выпуске, вероятно, хорошая идея. Что может быть хорошим, над выражением if, с обширным тестированием отладки, чтобы удалить некоторую, пожалуй, лишнюю проверку ошибок, оптимизирующую для релизов. Также предупреждение о том, чтобы не ставить логику изменения состояния в круглую скобку утверждения, так как результирующая логика не будет существовать в версиях сборки ... таким образом, с помощью assert (x ++ <12), например, x ++ не существует в версиях сборки, только в отладке. – Kit10

1

static_assert - это директива для компилятора. Он позволяет проверять информацию о типе во время компиляции. Это приведет к сбою компиляции и вызовет сообщение об ошибке, которое в большинстве IDE будет обнаружено и отображено в окне ошибки IDE.

static_assert(sizeof(int) == 4,"int should be 4 bytes"); 

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

assert(("mypointer should never be null!", mypointer != nullptr)); 
+1

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

+0

Макрос утверждения, определенный в '', не принимает двух аргументов – Joe

+0

@joe, справа, исправлен синтаксис. –

11

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

6

ОК, я укушу:

  • static_assert Только работы, если вы хотите, чтобы остановить компиляцию неудачно, если статическое состояние нарушается: static_assert(sizeof(void*) != 3, "Wrong machine word size"); * Только динамические утверждения могут поймать динамические условия: assert(argc == 1);

  • Простые if утверждения должны быть действительными и компилируемыми; статические утверждения вызывают сбои компиляции.

  • Номер

*) Практический пример может быть, чтобы предотвратить злоупотребления общих шаблонов конструкций, таких как int x; std::move<int&&>(x).

3

Неплохая практика их использования?

Если злоупотребление, да, в частности assert.

Оскорбление в зависимости от этих assert утверждений должно быть активным. Вы никогда не должны зависеть от assert, чтобы сделать что-либо, потому что код можно скомпилировать с помощью NDEBUG, а затем assert ничего не делает. Производственный код часто компилируется с NDEBUG, определенным для обеспечения исчезновения этих операторов assert.

Если вы не пишете одноразовую программу, которая не будет проживать более суток или двух, вы не должны использовать для проверки ввода пользователя. Пользователям все равно, где код не удался, а печатное сообщение выглядит как иностранный язык для многих пользователей. Он не сообщает пользователю, как исправить ошибку. Это также очень неумолимо, по дизайну. Сообщение, выпущенное в ответ на ошибку ввода пользователя, должно быть сообщением, которое сообщает пользователю, как исправить проблему. Лучшее действие после сообщения - предложить пользователю способ исправить ошибку. Если это невозможно сделать, и если единственным жизнеспособным ответом является завершение программы, программа должна прекратиться. По дизайну assert не приводит к чистому отключению. Он называет abort(), а не exit().

Одним из последствий abort() на многих машинах является создание дампа сердечника. Дамп ядра - отличное сообщение об ошибке для программиста. С дампом ядра программист может использовать отладчик, чтобы увидеть, что пошло не так в деталях. Недостатком abort() является то, что вещи не очищены. Abort "завершает программу без выполнения деструкторов для объектов с автоматическим или статическим хранением и без вызова функций, переданных в atexit()."

Нижняя строка: нормально (и хорошо) использовать assert для проверки ошибок программирования, но только в непроизводственной настройке. Используйте что-то еще, чтобы проверить ошибки пользователя.

Смежные вопросы