2017-01-27 29 views
0

Допустим, у меня есть следующие настройки в C++ программы, в глобальном масштабе/пространства имен (вне любого блока):Экстерн Const, что декларация и которая является опережающим объявлением

Ситуации 1:

a.cpp

extern const int i=5; 

b.cpp

extern const int i; 

Есть два способа, на мой взгляд, что компилятор мог это видеть. Один из них заключается в том, что истинное объявление i находится в b.cpp, а a.cpp имеет просто объявление вперед и инициализацию. (Поскольку мы знаем, что для конкретных extern consts инициализация во время объявления не требуется). Другой возможный исполняемый файл, который мог бы сгенерировать компилятор, должен иметь a.cpp, содержащий истинное объявление, с инициализацией и утверждение в b.cpp как прямое объявление, просто требуется, чтобы он помог компилятору узнать, что я есть.

Как компилятор определяет, какой файл отвечает за фактическое объявление, и, следовательно, распределение памяти, связанное с i? Это может иметь внешне наблюдаемые эффекты, если вместо int использовался тип с интересным конструктором.

Как ответ на этот вопрос изменения, если вообще, с:

ситуации 2:

a.cpp

extern const int i; 
extern const int i=5; 

b.cpp

extern const int i; 
+0

Вы объявляете это 'extern', и вы также говорите, что знаете его значение. Это кажется неправильным. – tadman

+0

@tadman При компиляции ошибок нет. Почему это неправильно? Я думал, что «extern» означает, что имя идентификатора имеет внешнюю связь. Это также означает, что вы не можете инициализировать его до известного значения? – Jeff

+0

Обычно 'extern' означает« хранится в другом файле », и компоновщик позаботится о его синхронизации. Как вы все это компилируете? – tadman

ответ

2

Присутствие инициализатора немедленно превращает декларацию в определение (за небольшим исключением, не имеющим отношения к нашему контексту). Это означает, что

extern const int i = 5; 

является определение вашего i. Он определяет i и дает ему внешнюю связь, то есть создает фактический i и делает его видимым для других единиц перевода («экспортирует» его).

Между тем,

extern const int i; 

не является определяющим, если декларация i. В основном это говорит о том, что i определен в другом месте («импортирует» его).

Когда вы по какой-то причине необходимо глобальное const объект в C++, собственно явное применение extern приобретает решающее значение, так как в C++ constобъекты имеют внутреннюю связь по умолчанию.

Просто имейте в виду, что для того, чтобы объект const int имел право на интегральные константные выражения (ICE), объявление этого объекта const int с инициализатором ICE должно быть видимым.

+0

что происходит в ситуации 2, когда оба файла имеют выражение extern const int, и ни одна из них не привязана к инициализации, которая возникает после этого в a.cpp? – Jeff

+0

@Jeff: Ничего особенного. У вас есть несколько не определяющих деклараций для 'i' (что является штрафным штрафом, вы можете иметь неограниченное количество) и одно определение' i' (у вас может быть не более одного). Итак, все в порядке. Компонент будет правильно связывать все вместе. – AnT

+0

Похоже, вы говорите, что в ситуации 2 «extern const int i = 5;» является определяющим. Но я смущен тем, какой из 3-х утверждений в ситуации 2 отвечает за распределение памяти для i. То есть когда я впервые возник? Другой способ задать это, из двух внешних констант int i; операторов в файлах a.cpp и b.cpp, один является реальным объявлением, а другой - хедз-ап компилятором о том, какой тип данных i представляет. Что это? Благодаря! – Jeff