Нет.Например, рассмотрим следующее:
int badfunc(int &a, int &b) {
return func(a++, b++);
}
Это имеет неопределенное поведение, если a
и b
имеют одинаковый реферранд.В общем, компилятор не может знать, какие аргументы будут переданы функции, поэтому он не может надежно уловить этот случай неопределенного поведения.Поэтому он не может перехватить все неопределенное поведение.
Предупреждения компилятора служат для идентификации некоторых случаев неопределенного поведения, но не всех.
Теоретически вы можете написать C ++реализация, которая выполняет огромное количество проверок во время выполнения, чтобы гарантировать, что неопределенное поведение всегда идентифицируется и обрабатывается способами, определенными этой реализацией.Он все равно не скажет вам во время компиляции (см .: проблема остановки), и на практике вам, вероятно, будет лучше с C #, который был разработан, чтобы сделать необходимые проверки во время выполнения достаточно эффективными ...
Даже если вы создали эту магическую реализацию C ++, она все равно может не сказать вам, что вы действительно хотите знать, а именно, является ли ваш код правильным.Иногда (держитесь за свои места), это определяется реализацией, является ли поведение неопределенным.Для простого примера tolower((char)-1);
имеет определенное поведение [*], если тип char
не подписан, но неопределенное поведение, если тип char
подписан.
Так что, если ваша волшебная реализация проверки не выполнит всетот же выбор реализации, что и в «реальной» реализации, на которой вы хотите, чтобы ваш код выполнялся, он не скажет вам, определил ли код поведение для набора вариантов реализации, сделанных в «реальной» реализации, только если он определилповедение для вариантов реализации, сделанных в реализации магической проверки.
Чтобы знать, что ваш код корректен и переносим, вам нужно знать (для начала), что он не дает неопределенного поведения для любого множество вариантов реализации.И, в этом отношении, для любого входа, а не только входов, используемых в ваших тестах.Вы можете подумать, что это большой недостаток C ++ по сравнению с языками без неопределенного поведения.Конечно, это иногда неудобно и влияет на то, как вы работаете с песочницами для безопасности.На практике, однако, чтобы вы считали свой код правильным, вам нужно не просто иметь определенное поведение, вам нужно поведение, соответствующее документу спецификации.Это намного большая проблема, и на практике написать ошибку в (скажем) Java или Python не намного сложнее, чем в C ++.Я написал бесчисленные ошибки во всех трех, и зная, что в Java или Python поведение было определено, но неправильное не очень мне помогло.
[*] Что ж, результат все еще определяется реализацией, это зависит от набора символов выполнения, но реализация должна возвращать правильный результат.Если подписано char
, это может привести к сбою.