C ++ семантика `статичного const` проти` const`


149

Що стосується конкретного C ++, які семантичні відмінності, наприклад:

static const int x = 0 ;

і

const int x = 0 ;

як staticв якості зв’язку, так і специфікатора класу зберігання (тобто всередині і зовні функції).


7
staticє, мабуть, найбільш перевантаженим ключовим словом у C ++. Значення вашого коду значно варіюється в залежності від того, чи знаходиться він в області простору імен, в області класу або в області функцій. Ви можете уточнити це.
sbi

1
@sbi: Я думав, що вже зробив. Область функцій (де це специфікатор класу зберігання) та область файлу (де це специфікатор зв'язку). Класифіковані змінні учасників класу та простори імен мене не хвилюють стосовно цього питання, хоча якщо хтось відчуває, що є цікаве розмежування, сміливо також висвітлюйте це.
Кліффорд

@Clifford: Вибачте, що я не помітив цих останніх слів. Однак це виявило непорозуміння з вашого боку: У C ++ область файлу - це область простору імен. Якщо ви декларуєте що-небудь поза будь-якого простору імен, воно просто належатиме до глобального простору імен (і доступне через префікс ::без ідентифікатора попереду). Мені невідомі якісь значущі відмінності між глобальним простором імен та будь-яким простором імен, вкладеним у ньому. Що стосується staticпредметів, звичайно, немає .
sbi

1
зв'язок відрізняється від видимості , використовуючи їх взаємозамінно, ви збираєтесь плутати людей, з якими спілкуєтесь, і, ймовірно, і себе.
Бен Войгт

1
@Ben, @sbi: Я не мав наміру припускати, що область файлу та статична зв'язок однакові, лише те, що статична зв'язок передбачає обсяг файлу. У цьому сенсі сфера (або видимість) є атрибутом статичної та зовнішньої зв'язку, а не синонімом ні для одного. Я вважаю, що первісне питання залишається чітким і добре сформованим, і що ми просто обговорюємо коментарі, зроблені у відповідь на дещо поблажливе зауваження sbi. Тут ми обговорюємо неточну семантику англійської мови, а не моє розуміння, тому я думаю, що ми можемо зупинитися.
Кліффорд

Відповіді:


128

У області файлу немає різниці в C ++. constробить внутрішню зв'язок за замовчуванням, а всі глобальні змінні мають статичний термін служби. Але перший варіант має таку саму поведінку в C, що може бути вагомим приводом для його використання.

У межах функції, друга версія може бути обчислена за параметрами. У C або C ++ це не повинно бути константою часу компіляції, як вимагають деякі інші мови.

В межах класу - це те саме, що і для функцій. constЗначення екземпляра може бути обчислено у списку ctor-ініціалізатора . A static constвстановлюється під час ініціалізації запуску і залишається незмінним для решти програми. (Примітка: код для staticчленів виглядає дещо інакше, оскільки декларація та ініціалізація розділені.)

Пам'ятайте, що в C ++ constозначає лише читання , а не постійне . Якщо у вас є вказівник на, constтоді інші частини програми можуть змінювати значення, поки ви не дивитесь. Якщо змінна була визначена за допомогою const, то ніхто не може змінити її після ініціалізації, але ініціалізація все ще може бути довільно складною.


1
Чи є щось, що називається область файлу? Я тільки перевіряв $ 3,3, і я думаю, що найближчим є «область простору імен». Чи правильно моє розуміння? Стандарт C ++ 03 згадує область файлів лише у Додатках
Чубсдад

2
Я б припустив, що область файлів - це артефакт посилання, а не компілятор, тому, можливо, не буде приділено великої уваги мовному стандарту. Суворо це, мабуть, "область одиниці компіляції".
Кліффорд

8
+1 для фрази "const означає лише читання, а не постійне", тобто "Компілятор, якщо ви бачите, що хтось намагається змінити цю річ const, гавкайте дуже голосно". Це є причиною, що щось може бути одночасно і мінливим.
День

5
Це більше "Компілятор, якщо ви бачите, що я намагаюся змінити цю річ const (або дати комусь іншому дозвіл на це)", гавкайте дуже голосно. У більшості контекстів constстосується подання змінної, а не самої змінної, у когось іншого може бути відсутність constперегляду тієї самої змінної, і компілятор буде абсолютно беззвучним, коли вони модифікують її.
Ben Voigt

1
@Ben: Щоб зрозуміти, C ++ 0x не знімає конкретного використання const, але constexprзамість цього можна використовувати нове (і в інших сценаріях). Насправді стандарт C ++ 0x розширює можливість використання constв цьому сценарії і до неінтегральних "буквальних типів". Я думаю, що я вважаю за краще використовувати constexprдля цих випадків, оскільки ви все одно порушите сумісність із компіляторами до C ++ 0x.
Майкл Берр

4

C ++ 17 стандартних чернеток на constувазі, що стосуються staticфайлу

Це цитата, про яку згадувалося на сайті: https://stackoverflow.com/a/3709257/895245

C ++ 17 n4659 стандартний проект 6.5 "Програма та зв'язок":

3 Ім'я, яке має область простору імен (6.3.6), має внутрішні зв'язки, якщо це ім'я

  • (3.1) - шаблон змінної, функції або функції, який явно оголошений статичним; або,
  • (3.2) - нелінійна змінна типу енергонезалежного типу const, яка не є явно оголошеною зовнішньою, або раніше заявленою, щоб мати зовнішню зв'язок; або
  • (3.3) - член даних анонімного об'єднання.

Додаток C (інформативна) сумісність, C.1.2 п. 6: "основні поняття" дає обґрунтування, чому це було змінено з C:

6.5 [також 10.1.7]

Зміни: ім'я області файлу, яка явно оголошена const, а не явно оголошена extern, має внутрішню зв'язок, тоді як у C вона мала б зовнішню зв'язок.

Обгрунтування: Оскільки об'єкти const можуть використовуватися як значення під час перекладу в C ++, ця функція закликає програмістів надати явний ініціалізатор для кожного об'єкту const. Ця функція дозволяє користувачеві розміщувати об'єкти const у вихідних файлах, які входять у більш ніж один блок перекладу.

Вплив на оригінальну особливість: Перехід до семантики чітко визначеної ознаки.

Складність перетворення: семантична трансформація.

Як широко використовується: Рідко.

Дивіться також: Чому const передбачає внутрішню зв'язок у C ++, якщо він не в C?

Що ви, швидше за все, хочете зробити замість заголовків

Детально пояснено на: Що означає "const статична" в C і C ++?

  • до C ++ 17: externу заголовку, визначення у файлі cpp
  • повідомлення C ++ 17: вбудована змінна на заголовку

Дякую, хоча я не думаю, що це шанс у C ++ 17 порівняно навіть із C ++ 98, і це питання було задано у 2010 році. Більше того, ваша відповідь стосується лише статики як специфікатора зв'язку (в області простору імен) , і питання, що задається конкретно про семантику в різних контекстах.
Кліффорд

@Clifford так, безумовно, старше C ++ 17, просто лінь читати всі стандарти ;-) Роз'ясне частину області файлу.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.