Embora seja verdade que o comportamento é bem definido - é não verdade que compiladores pode "otimizar para const", no sentido que você quer dizer.
Ou seja, não é permitido que um compilador assuma que apenas porque um parâmetro é a const T* ptr
, a memória apontada por ptr
não será alterada por outro ponteiro. Os ponteiros nem precisam ser iguais. A const
é uma obrigação, não uma garantia - uma obrigação por você (= a função) não fazer alterações por meio desse ponteiro.
Para realmente ter essa garantia, você precisa marcar o ponteiro com a restrict
palavra - chave. Portanto, se você compilar essas duas funções:
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;
}
a foo()
função deve ler duas vezes x
, enquanto bar()
só precisa ler uma vez:
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
Veja isso ao vivo GodBolt.
restrict
é apenas uma palavra-chave em C (desde C99); infelizmente, ele não foi introduzido no C ++ até agora (pelo baixo motivo que é mais complicado introduzi-lo no C ++). Muitos compiladores suportam isso, no entanto, como __restrict
.
Conclusão: O compilador deve oferecer suporte ao seu caso de uso "esotérico" ao compilar f()
e não terá nenhum problema com ele.
Consulte esta postagem sobre casos de uso para restrict
.
const
não é "uma obrigação sua (= a função) de não fazer alterações através desse ponteiro". O padrão C permite que a função seja removidaconst
por meio de uma conversão e, em seguida, modifique o objeto através do resultado. Essencialmente,const
é apenas um aviso e uma conveniência para o programador para ajudar a evitar a modificação inadvertida de um objeto.