Muitas respostas razoáveis já. Vou abordar uma analogia que pode ajudar alguns leitores. ::
funciona muito parecido com o separador de diretório do sistema de arquivos ' /
', ao pesquisar seu caminho para um programa que você gostaria de executar. Considerar:
/path/to/executable
Isso é muito explícito - apenas um executável no local exato na árvore do sistema de arquivos pode corresponder a essa especificação, independentemente do PATH em vigor. Similarmente...
::std::cout
... é igualmente explícito no espaço para nome C ++ "árvore".
Contrastando com esses caminhos absolutos, você pode configurar boas shells do UNIX (por exemplo, zsh ) para resolver caminhos relativos no diretório atual ou em qualquer elemento da PATH
variável de ambiente, por isso PATH=/usr/bin:/usr/local/bin
, se você estiver dentro /tmp
, então ...
X11/xterm
... seria executado feliz /tmp/X11/xterm
se encontrado, mais /usr/bin/X11/xterm
, mais /usr/local/bin/X11/xterm
. Da mesma forma, digamos que você estava em um espaço para nome chamado X
e teve um " using namespace Y
" efeito, então ...
std::cout
... pode ser encontrada em qualquer um ::X::std::cout
, ::std::cout
, ::Y::std::cout
, e possivelmente outros lugares devido à pesquisa dependentes do argumento (ADL, também conhecido como Koenig lookup). Portanto, apenas ::std::cout
é realmente explícito exatamente exatamente qual objeto você quer dizer, mas felizmente ninguém em seu perfeito juízo jamais criaria sua própria classe / estrutura ou espaço de nome chamado " std
", nem qualquer coisa chamada " cout
", portanto, na prática, usar apenas std::cout
está bem.
Diferenças notáveis :
1) shells tendem a usar a primeira correspondência usando a ordem de entrada PATH
, enquanto o C ++ gera um erro de compilador quando você é ambíguo.
2) No C ++, nomes sem nenhum escopo à frente podem ser correspondidos no namespace atual, enquanto a maioria dos shells do UNIX só fazem isso se você inserir .
o PATH
.
3) O C ++ sempre pesquisa no espaço para nome global (como ter /
implicitamente o seu PATH
).
Discussão geral sobre namespaces e explicitação de símbolos
::abc::def::...
Às vezes, o uso de "caminhos" absolutos pode ser útil para isolá-lo de qualquer outro espaço de nome que você esteja usando, parte de, mas realmente não tem controle sobre o conteúdo ou mesmo outras bibliotecas que o código de cliente da sua biblioteca também usa. Por outro lado, também o acopla mais firmemente ao local "absoluto" existente do símbolo e você perde as vantagens da correspondência implícita nos espaços para nome: menos acoplamento, mobilidade mais fácil do código entre espaços para nome e código-fonte legível e conciso .
Como em muitas coisas, é um ato de equilíbrio. Os puts lotes C ++ padrão dos identificadores sob std::
que são menos "único" do que cout
, que os programadores podem usar para algo completamente diferente no seu código (por exemplo merge
, includes
, fill
, generate
, exchange
, queue
, toupper
, max
). Duas bibliotecas não-padrão não relacionadas têm uma chance muito maior de usar os mesmos identificadores, já que os autores geralmente não têm ou menos consciência um do outro. E as bibliotecas - incluindo a biblioteca C ++ Standard - alteram seus símbolos ao longo do tempo. Tudo isso potencialmente cria ambiguidade ao recompilar o código antigo, principalmente quando há um uso pesado de using namespace
s: a pior coisa que você pode fazer nesse espaço é permitirusing namespace
s nos cabeçalhos para escapar do escopo dos cabeçalhos, de forma que uma quantidade arbitrariamente grande de código de cliente direto e indireto não consiga tomar suas próprias decisões sobre quais namespaces usar e como gerenciar ambiguidades.
Portanto, um líder ::
é uma ferramenta na caixa de ferramentas do programador C ++ para desambiguar ativamente um conflito conhecido e / ou eliminar a possibilidade de ambiguidade futura.
::
meios nus referenciam a variável do namespace global / anônimo.