Хоча це правда , що поведінка визначено коректно - це НЕ правда , що компілятори можуть «оптимізувати для сопзЬ» в тому сенсі , що ви маєте в виду.
Тобто компілятору не дозволяється припускати, що лише тому, що параметр є a 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.
Підсумок: компілятор повинен підтримувати ваш "езотеричний" випадок використання при компілюванні f(), і не матиме з цим жодних проблем.
Дивіться цю публікацію щодо випадків використання для restrict.
constне є "зобов'язанням з боку вас (= функція) не вносити змін через цей покажчик". Стандарт C дозволяє виконувати функцію видаленняconstза допомогою кастра, а потім модифікувати об'єкт через результат. По суті,constце лише рекомендація та зручність для програміста, щоб допомогти уникнути зміни об'єкта ненавмисно.