Подтвердить что ты не робот

В чем разница между assert и static_assert?

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

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

Ответ 1

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

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

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

  • Делают ли они что-либо, что не может сделать простой оператор if?

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

  • Используется ли им плохая практика?

Совсем нет!

Ответ 2

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

Ответ 3

ОК, я укушу:

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

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

  • Нет.

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

Ответ 4

Используется ли им плохая практика?

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

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

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

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

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

Ответ 5

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

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

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

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