Много разумных ответов уже. Я приведу аналогию, которая может помочь некоторым читателям. ::
работает так же, как разделитель каталогов файловой системы '/
', при поиске в вашем пути программы, которую вы хотите запустить. Рассмотрим:
/path/to/executable
Это очень явно - только исполняемый файл в этом точном месте в дереве файловой системы может соответствовать этой спецификации, независимо от действующего PATH. Точно так же ...
::std::cout
... в явном виде в пространстве имен C ++ "tree".
В отличие от таких абсолютных путей, вы можете настроить хорошие оболочки 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, он же поиск Кенига). Таким образом, только ::std::cout
точно указывает, какой именно объект вы имеете в виду, но, к счастью, никто в здравом уме никогда не создаст свой собственный класс / структуру или пространство имен с именем "std
" или что-либо с именем "cout
", поэтому на практике использовать только std::cout
хорошо.
Примечательные различия :
1) оболочки обычно используют первое совпадение, используя порядок в PATH
, тогда как C ++ выдает ошибку компилятора, когда вы неоднозначны.
2) В C ++ имена без какой-либо ведущей области могут быть сопоставлены в текущем пространстве имен, в то время как большинство оболочек UNIX делают это, только если вы добавите .
в PATH
.
3) C ++ всегда ищет глобальное пространство имен (например, /
неявно указывает ваш PATH
).
Общее обсуждение пространств имен и явности символов
Использование абсолютных ::abc::def::...
«путей» иногда может быть полезно, чтобы изолировать вас от любых других пространств имен, которые вы используете, частично, но на самом деле не контролируете содержимое или даже другие библиотеки, которые код клиента вашей библиотеки также использует. С другой стороны, он также более тесно связывает вас с существующим «абсолютным» расположением символа, и вы упускаете преимущества неявного сопоставления в пространствах имен: меньшая связь, более легкая мобильность кода между пространствами имен и более лаконичный, читаемый исходный код .
Как и во многих вещах, это уравновешивающее действие. Стандарт C ++ помещает множество идентификаторов в std::
, которые менее «уникальны», чем cout
, которые программисты могут использовать для чего-то совершенно другого в своем коде (например, merge
, includes
, fill
, generate
, exchange
, queue
, toupper
, max
). Две несвязанные нестандартные библиотеки имеют гораздо более высокую вероятность использования тех же идентификаторов, что авторы, как правило, не знают или не знают друг друга. И библиотеки, включая стандартную библиотеку C ++, со временем меняют свои символы. Все это потенциально создает двусмысленность при перекомпиляции старого кода, особенно когда интенсивно используется using namespace
s: самое худшее, что вы можете сделать в этом пространстве, это разрешить using namespace
s в заголовках выходить из области заголовков, так что произвольно Большое количество прямого и косвенного клиентского кода не может самостоятельно принимать решения о том, какие пространства имен использовать и как управлять неоднозначностями.
Итак, ведущий ::
- это один из инструментов в наборе инструментов для программиста C ++, позволяющий активно устранять неоднозначность известного столкновения и / или устранять возможность будущей неоднозначности ....