Хотя верно, что поведение четко определено - это не верно, что компиляторы могут "оптимизировать для const" в том смысле, который вы имеете в виду.
То есть компилятор не допускается, если предположить, что только из-за параметра const T* ptr
память, на которую указывает ptr
, не будет изменена через другой указатель. Указатели даже не должны быть равны. const
является обязательством, а не гарантией - обязательство вами (= функция) не вносить изменения с помощью этого указателя.
Чтобы получить эту гарантию, вам необходимо пометить указатель с помощью ключевое слово restrict
. Таким образом, если вы скомпилируете эти две функции:
int foo(const int* x, int* y) {
int result = *x;
(*y)++;
return result + *x;
}
int bar(const int* x, int* restrict y) {
int result = *x;
(*y)++;
return result + *x;
}
, функция foo()
должна прочитать дважды из x
, в то время как bar()
нужно прочитать только один раз:
foo:
mov eax, DWORD PTR [rdi]
add DWORD PTR [rsi], 1
add eax, DWORD PTR [rdi] # second read
ret
bar:
mov eax, DWORD PTR [rdi]
add DWORD PTR [rsi], 1
add eax, eax # no second read
ret
Смотрите это в прямом эфире на GodBolt .
restrict
является только ключевым словом в C (начиная с C99); к сожалению, он до сих пор не введен в C ++ (по плохой причине, так как его сложнее ввести в C ++). Однако многие компиляторы поддерживают его вроде как __restrict
.
Итог: компилятор должен поддерживать ваш вариант использования "esoteri c" при компиляции f()
и не будет иметь никаких проблем с it.
См. этот пост относительно вариантов использования для restrict
.