Хоча це правда , що поведінка визначено коректно - це НЕ правда , що компілятори можуть «оптимізувати для сопзЬ» в тому сенсі , що ви маєте в виду.
Тобто компілятору не дозволяється припускати, що лише тому, що параметр є 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
це лише рекомендація та зручність для програміста, щоб допомогти уникнути зміни об'єкта ненавмисно.