Muchas respuestas razonables ya. Voy a incluir una analogía que puede ayudar a algunos lectores. ::
funciona muy parecido al separador de directorio del sistema de archivos ' /
', cuando busca en su ruta un programa que le gustaría ejecutar. Considerar:
/path/to/executable
Esto es muy explícito: solo un ejecutable en esa ubicación exacta en el árbol del sistema de archivos puede coincidir con esta especificación, independientemente de la RUTA vigente. Similar...
::std::cout
... es igualmente explícito en el "árbol" del espacio de nombres C ++.
En contraste con tales rutas absolutas, puede configurar buenos shells UNIX (por ejemplo, zsh ) para resolver rutas relativas bajo su directorio actual o cualquier elemento en su PATH
variable de entorno, por lo que si PATH=/usr/bin:/usr/local/bin
, y estuviera "en" /tmp
, entonces ...
X11/xterm
... correría feliz /tmp/X11/xterm
si lo encontraran, de lo contrario /usr/bin/X11/xterm
, de lo contrario /usr/local/bin/X11/xterm
. Del mismo modo, digamos que estaba en un espacio de nombres llamado X
y tenía un " using namespace Y
" en efecto, entonces ...
std::cout
... se puede encontrar en cualquiera de ::X::std::cout
, ::std::cout
, ::Y::std::cout
, y posiblemente en otros lugares debido a las operaciones de búsqueda argumento dependiente (ADL, también conocido como búsqueda Koenig). Entonces, solo ::std::cout
es realmente explícito sobre exactamente a qué objeto te refieres, pero afortunadamente nadie en su sano juicio crearía su propia clase / estructura o espacio de nombre llamado " std
", ni nada llamado " cout
", por lo que en la práctica usar solo std::cout
está bien.
Diferencias notables :
1) los shells tienden a usar la primera coincidencia usando el orden PATH
, mientras que C ++ da un error de compilación cuando has sido ambiguo.
2) En C ++, los nombres sin ningún alcance inicial pueden coincidir en el espacio de nombres actual, mientras que la mayoría de los shells de UNIX solo lo hacen si se coloca .
en el PATH
.
3) C ++ siempre busca el espacio de nombres global (como tener /
implícitamente su PATH
).
Discusión general sobre espacios de nombres y explicidad de símbolos
El uso de ::abc::def::...
"rutas" absolutas a veces puede ser útil para aislarlo de cualquier otro espacio de nombres que esté usando, parte de, pero realmente no tiene control sobre el contenido o incluso otras bibliotecas que el código del cliente de su biblioteca también usa. Por otro lado, también lo acopla más estrechamente a la ubicación "absoluta" existente del símbolo, y pierde las ventajas de la coincidencia implícita en los espacios de nombres: menos acoplamiento, movilidad más fácil del código entre espacios de nombres y código fuente más conciso y legible .
Como con muchas cosas, es un acto de equilibrio. Los C ++ estándar puts un montón de identificadores en virtud std::
de que son menos "única" que cout
, que los programadores pueden utilizar para algo completamente diferente en su código (por ejemplo merge
, includes
, fill
, generate
, exchange
, queue
, toupper
, max
). Dos bibliotecas no estándar no relacionadas tienen una probabilidad mucho mayor de usar los mismos identificadores que los autores generalmente no se conocen entre sí. Y las bibliotecas, incluida la biblioteca estándar de C ++, cambian sus símbolos con el tiempo. Todo esto potencialmente crea ambigüedad al volver a compilar el código antiguo, especialmente cuando ha habido un uso intensivo de using namespace
s: lo peor que puede hacer en este espacio es permitirusing namespace
s en encabezados para escapar de los ámbitos de los encabezados, de modo que una cantidad arbitrariamente grande de código de cliente directo e indirecto no puede tomar sus propias decisiones sobre qué espacios de nombres usar y cómo gestionar las ambigüedades.
Entonces, un líder ::
es una herramienta en la caja de herramientas del programador C ++ para desambiguar activamente un choque conocido y / o eliminar la posibilidad de ambigüedad futura ...
::
medios desnudos hacen referencia a la variable del espacio de nombres global / anónimo.