S'il est vrai que le comportement est bien défini - il n'est pas vrai que les compilateurs peuvent "optimiser pour const" dans le sens que vous voulez dire.
Autrement dit, un compilateur n'est pas autorisé à supposer que, simplement parce qu'un paramètre est un const T* ptr
, la mémoire pointée par ptr
ne sera pas modifiée via un autre pointeur. Les pointeurs n'ont même pas besoin d'être égaux. C'est const
une obligation, pas une garantie - une obligation de votre part (= la fonction) de ne pas apporter de modifications via ce pointeur.
Afin d'avoir réellement cette garantie, vous devez marquer le pointeur avec le restrict
mot - clé. Ainsi, si vous compilez ces deux fonctions:
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()
fonction doit lire deux fois x
, alors qu'elle bar()
n'a besoin de la lire qu'une seule fois:
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
Regardez ça en direct GodBolt.
restrict
n'est qu'un mot-clé en C (depuis C99); malheureusement, il n'a pas encore été introduit en C ++ (pour la mauvaise raison qu'il est plus compliqué de l'introduire en C ++). Cependant, de nombreux compilateurs le supportent un peu comme __restrict
.
Conclusion: le compilateur doit prendre en charge votre cas d'utilisation "ésotérique" lors de la compilation f()
et n'aura aucun problème avec celui-ci.
Voir cet article concernant les cas d'utilisation de restrict
.
const
n'est pas «une obligation de votre part (= la fonction) de ne pas apporter de modifications via ce pointeur». La norme C permet à la fonction de supprimerconst
via un cast puis de modifier l'objet à travers le résultat. Essentiellement, ceconst
n'est qu'un conseil et une commodité pour le programmeur pour éviter de modifier un objet par inadvertance.