2015-11-23 6 views
8

Этот вопрос напрямую связан с this one. Рассмотрим код:Имеют ли встроенные переменные пространства имен внутреннюю связь? Если нет, то почему код ниже работает?

#include <iostream> 

inline namespace N1 
{ 
    int x = 42; 
} 
int x = 10; 

int main() 
{ 
    extern int x; 
    std::cout << x; // displays 10 
} 

Он отображает 10. Если удалить extern int x; декларацию, то мы получаем ошибку времени неоднозначность компилятор

error: reference to 'x' is ambiguous

Вопрос: почему код работы с Декларацией работы extern int x, и почему он перестает работать, когда я удалить его? Это потому, что переменные пространства inline имеют внутреннюю связь?

+0

Они не имеют внутренней связи, если они не заключены в неназванное пространство имен. Вы сбиваете с толку встроенные и неназванные? –

+0

@ T.C. Нет, я не путаю их. Я знал, что неназванные пространства имен имеют внутреннюю связь. – vsoftco

+0

Возможно, вы должны перефразировать вопрос «почему это работает», поскольку вы, вероятно, больше заинтересованы в этом, чем в строго логическом ответе на то, действительно ли переменные пространства имен имеют статическое хранилище или внутреннюю связь (это то, что соответствует текущему адресу ответов). – zneak

ответ

2

Нет. Нет данных в [basic.link], что привело бы к тому, что x имел внутреннюю связь. В частности, «Все остальные пространства имен имеют внешнюю связь», а «другое» относится к «не неназванным». Возможно, вы думали о неназванных пространствах имен?

+0

Я знаю, что конкретно не спрашивал ОП, но почему тогда добавление extern фиксирует двусмысленность? – Borgleader

+0

@Borgleader: по той же причине, что 'extern' выбирает самое внешнее имя в' int x; {int x; {int x; {int x; {extern int x; x = 10; }}}} '? –

+0

Ну ладно, имеет смысл. Благодарю. – Borgleader

1

Нет, код работает, потому что, чтобы не нарушать существующий код C, extern int x; должен работать так же, как в C, другими словами, создавая локальный extern для глобального пространства имен (это все, что у нас было в C). Затем, когда вы используете его позже, локально объявленный extern удаляет любую возможную двусмысленность.

+0

Он относится к самому внутреннему пространству имен, а не к глобальному пространству имен. Например. 'int x = 10; пространство имен S {int x = 20; void f() {extern int x; printf ("% d \ n", x);}} int main() {S :: f(); } 'prints' 20' –