Si bien es cierto que el comportamiento está bien definido - es no cierto que los compiladores pueden "optimizar para la const" en el sentido de que usted se refiere.
Es decir, un compilador no puede asumir que solo porque un parámetro sea a const T* ptr
, la memoria a la que apunta ptr
no se cambiará a través de otro puntero. Los punteros ni siquiera tienen que ser iguales. El const
es una obligación, no una garantía, una obligación suya (= la función) de no realizar cambios a través de ese puntero.
Para tener esa garantía, debe marcar el puntero con la restrict
palabra clave. Por lo tanto, si compila estas dos funciones:
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;
}
la foo()
función debe leer dos veces x
, mientras que bar()
solo necesita leerla una 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
Mira esto en vivo GodBolt.
restrict
es solo una palabra clave en C (desde C99); desafortunadamente, no se ha introducido en C ++ hasta ahora (por la mala razón de que es más complicado introducirlo en C ++). Sin embargo, muchos compiladores sí lo admiten __restrict
.
En pocas palabras: el compilador debe admitir su caso de uso "esotérico" al compilar f()
, y no tendrá ningún problema.
Vea esta publicación sobre casos de uso para restrict
.
const
no es "una obligación suya (= la función) no hacer cambios a través de ese puntero". El estándar C permite que la función se elimineconst
mediante una conversión y luego se modifique el objeto a través del resultado. Esencialmente,const
es solo una asesoría y una conveniencia para el programador para ayudar a evitar modificar un objeto sin darse cuenta.