[Редагувати: Добре, тому це питання є більш тонким, ніж я думав спочатку.]
Оголошення покажчика на const або посилання на const ніколи не допомагає жодному компілятору щось оптимізувати. (Хоча див. Оновлення внизу цієї відповіді.)
constДекларація вказує на те, як тільки ідентифікатор буде використовуватися в межах обсягу його декларації; це не говорить про те, що основний об'єкт не може змінитися.
Приклад:
int foo(const int *p) {
int x = *p;
bar(x);
x = *p;
return x;
}
Компілятор не може припустити, що *pце не змінено викликом bar(), оскільки pможе бути (наприклад, вказівником на глобальний int і bar()може змінити його.
Якщо компілятор знає достатньо про того, хто викликає, foo()і вміст, bar()який він може довести bar(), не змінює *p, то він може також виконати цей доказ без оголошення const .
Але це справедливо загалом. Оскільки constефект впливає лише на обсяг декларації, компілятор вже може бачити, як ви обробляєте вказівник або посилання в межах цього обсягу; воно вже знає, що ви не модифікуєте базовий об'єкт.
Тож коротше, все, що constробиться в цьому контексті, це заважає вам робити помилки. Він не повідомляє компілятору нічого, чого він ще не знає, і тому він не має значення для оптимізації.
А як щодо функцій, які викликають foo()? Подібно до:
int x = 37;
foo(&x);
printf("%d\n", x);
Чи може компілятор довести, що це друкує 37, оскільки foo()приймає a const int *?
Ні. Незважаючи на те, що foo()приймає покажчик на const, він може відкинути const-ness і змінити int. (Це не є невизначеною поведінкою.) І тут компілятор взагалі не може робити жодних припущень; і якщо він знає достатньо про те, foo()щоб зробити таку оптимізацію, він буде знати, що навіть без const.
Єдиний час, який constможе дозволити оптимізацію, - це такі випадки:
const int x = 37;
foo(&x);
printf("%d\n", x);
Тут модифікувати за xдопомогою будь-якого механізму (наприклад, взявши вказівник на нього та відкинувши його const) означає викликати невизначену поведінку. Тож компілятор може вільно припустити, що ви цього не робите, і він може розповсюдити константу 37 у printf (). Така оптимізація є законною для будь-якого об’єкта, який ви заявляєте const. (На практиці локальна змінна, на яку ви ніколи не посилаєтесь, не виграє, оскільки компілятор вже бачить, чи ви її змінюєте в межах своєї сфери дії.)
Щоб відповісти на ваше запитання "побічної ноти", (a) покажчик const - це покажчик; і (b) покажчик const може дорівнювати NULL. Ви праві, що внутрішнє подання (тобто адреса), швидше за все, однакове.
[оновлення]
Як зазначає Крістоф у коментарях, моя відповідь є неповною, оскільки в ній не згадується restrict.
Розділ 6.7.3.1 (4) стандарту C99 говорить:
Під час кожного виконання B, нехай L - будь-яке значення l, яке має & L на основі P. Якщо L використовується для доступу до значення об'єкта X, який він позначає, і X також модифікується (будь-якими способами), тоді застосовуються наступні вимоги : T не повинен бути кваліфікованим. ...
(Тут B - основний блок, над яким знаходиться P, обмежувач-покажчик на T).)
Отже, якщо функція C foo()оголошена так:
foo(const int * restrict p)
... тоді компілятор може припустити, що жодні зміни не *pвідбуватимуться протягом життя p- тобто під час виконання foo()- тому, що в іншому випадку поведінка була б невизначеною.
Отже, в принципі поєднання restrictз покажчиком на const може забезпечити обидві оптимізації, які відхилено вище. Цікаво, хтось із компіляторів реалізує таку оптимізацію? (GCC 4.5.2, принаймні, ні.)
Зверніть увагу, що restrictіснує лише в C, а не в C ++ (навіть не C ++ 0x), за винятком розширення, специфічного для компілятора.
const, але в основному для людей, і коду, який ми пишемо; компілятор не може нічому довіряти, а тому він не може розумно виграти таким же чином.