Много разумных ответов уже. Я приведу аналогию, которая может помочь некоторым читателям. ::
работает так же, как разделитель каталогов файловой системы ' /
', при поиске в вашем пути программы, которую вы хотите запустить. Рассматривать:
/path/to/executable
Это очень явно - только исполняемый файл в этом точном месте в дереве файловой системы может соответствовать этой спецификации, независимо от действующей переменной PATH. По аналогии...
::std::cout
... одинаково явно в пространстве имен C ++ "дерево".
В отличие от таких абсолютных путей, вы можете настроить хорошие оболочки UNIX (например, zsh ) для разрешения относительных путей в вашем текущем каталоге или любом элементе в вашей PATH
переменной среды, так что если PATH=/usr/bin:/usr/local/bin
, и вы были «в» /tmp
, то ...
X11/xterm
... с удовольствием побежал /tmp/X11/xterm
бы, если бы нашел, еще /usr/bin/X11/xterm
, еще /usr/local/bin/X11/xterm
. Точно так же, скажем, вы находились в пространстве имен, которое называлось X
и имело « using namespace Y
», тогда ...
std::cout
... можно найти в любом из ::X::std::cout
, ::std::cout
, ::Y::std::cout
, и , возможно , в других местах из - за аргументов в зависимости от поиска (ADL, известный Koenig поиск). Таким образом, только ::std::cout
в действительности четко указано, какой именно объект вы имеете в виду, но, к счастью, никто в здравом уме никогда не создаст свой собственный класс / структуру или пространство имен, называемое " std
", или что-либо, называемое " cout
", так что на практике использование только std::cout
хорошо.
Примечательные отличия :
1) оболочки обычно используют первое совпадение, используя порядок в PATH
, тогда как C ++ выдает ошибку компилятора, когда вы неоднозначны.
2) В C ++ имена без какой-либо ведущей области могут быть сопоставлены в текущем пространстве имен, в то время как большинство оболочек UNIX делают это только в том случае, если вы вставили .
в PATH
.
3) C ++ всегда ищет глобальное пространство имен (например, /
неявно ваше PATH
).
Общее обсуждение пространств имен и явности символов
Использование абсолютных ::abc::def::...
«путей» иногда может быть полезно, чтобы изолировать вас от любых других пространств имен, которые вы используете, частично, но на самом деле не контролируете содержимое или даже другие библиотеки, которые также использует клиентский код вашей библиотеки. С другой стороны, он также более тесно связывает вас с существующим «абсолютным» расположением символа, и вы упускаете преимущества неявного сопоставления в пространствах имен: меньшая связь, более легкая мобильность кода между пространствами имен и более лаконичный, читаемый исходный код ,
Как и во многих вещах, это уравновешивание. В C ++ Standard Оферта множество идентификаторов под std::
которые являются менее «уникальным» , чем cout
, что программисты могут использовать для чего - то совершенно другого в своем коде (например merge
, includes
, fill
, generate
, exchange
, queue
, toupper
, max
). Две несвязанные нестандартные библиотеки имеют гораздо более высокую вероятность использования тех же идентификаторов, что авторы, как правило, не знают или не знают друг друга. И библиотеки, включая стандартную библиотеку C ++, со временем меняют свои символы. Все это потенциально создает неоднозначность при перекомпиляции старого кода, особенно когда интенсивно используется using namespace
s: худшее, что вы можете сделать в этом пространстве, это разрешитьusing namespace
в заголовках, выходящих за рамки заголовков, так что произвольно большое количество прямого и косвенного клиентского кода не может самостоятельно принимать решения о том, какие пространства имен использовать и как управлять неоднозначностями.
Таким образом, ведущий ::
является одним из инструментов в наборе инструментов для программиста на C ++, позволяющим активно устранять неоднозначность известного столкновения и / или устранять возможность будущей неоднозначности ....
::
средства ссылаются на переменную из глобального / анонимного пространства имен.