Es stimmt zwar, dass das Verhalten genau definiert ist, aber es stimmt nicht , dass Compiler in dem von Ihnen gemeinten Sinne "für const optimieren" können.
Das heißt, ein Compiler darf nicht davon ausgehen, dass nur weil ein Parameter a ist const T* ptr
, der Speicher, auf den von ptr
zeigt, nicht durch einen anderen Zeiger geändert wird. Die Zeiger müssen nicht einmal gleich sein. Dies const
ist eine Verpflichtung, keine Garantie - eine Verpflichtung von Ihnen (= die Funktion), keine Änderungen über diesen Zeiger vorzunehmen.
Um diese Garantie tatsächlich zu haben, müssen Sie den Zeiger mit dem restrict
Schlüsselwort markieren . Wenn Sie also diese beiden Funktionen kompilieren:
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;
}
Die foo()
Funktion muss zweimal lesen x
, während sie bar()
nur einmal lesen muss:
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
Sehen Sie dies live weiter GodBolt.
restrict
ist nur ein Schlüsselwort in C (seit C99); Leider wurde es bisher nicht in C ++ eingeführt (aus dem schlechten Grund, dass die Einführung in C ++ komplizierter ist). Viele Compiler unterstützen es jedoch irgendwie als __restrict
.
Fazit: Der Compiler muss Ihren "esoterischen" Anwendungsfall beim Kompilieren f()
unterstützen und hat keine Probleme damit.
Siehe diesen Beitrag zu Anwendungsfällen für restrict
.
const
ist nicht „eine Verpflichtung von Ihnen (= der Funktion), keine Änderungen über diesen Zeiger vorzunehmen“. Der C-Standard ermöglicht es der Funktion,const
über einen Cast zu entfernen und das Objekt dann durch das Ergebnis zu modifizieren. Diesconst
ist im Wesentlichen nur eine Empfehlung und eine Annehmlichkeit für den Programmierer, um zu vermeiden, dass ein Objekt versehentlich geändert wird.