Я думаю, что второй опус То, что каждый программист C должен знать о неопределенном поведении , может помочь проиллюстрировать эту проблему.
На примере блога:
void contains_null_check(int *P) {
int dead = *P;
if (P == 0)
return;
*P = 4;
}
Может быть оптимизировано для (RNCE: исключение избыточной проверки нуля):
void contains_null_check_after_RNCE(int *P) {
int dead = *P;
if (false) // P was dereferenced by this point, so it can't be null
return;
*P = 4;
}
Что превращается в оптимизированный (DCE: Устранение мертвого кода):
void contains_null_check_after_RNCE_and_DCE(int *P) {
//int dead = *P; -- dead store
//if (false) -- unreachable branch
// return;
*P = 4;
}
Как вы можете видеть, даже если dead
никогда не используется , простое назначение int dead = *P
привело к ползучести в программе неопределенного поведения.
Чтобы различать перегрузки, я бы предложил использовать указатель (который может быть нулевым), а не искусственно создавать нулевую ссылку и подвергать себя неопределенному поведению.