c++ - sirve - ¿Por qué se considera una mala práctica el uso de "namespace std"?
using namespace dev c++ (30)
No lo uses globalmente.
Se considera "malo" solo cuando se usa globalmente . Porque:
- Usted desordena el espacio de nombres que está programando.
- Los lectores tendrán dificultades para ver de dónde proviene un identificador particular, cuando usa muchos
using namespace xyz
. - Lo que sea cierto para otros lectores de su código fuente es aún más cierto para el lector más frecuente: usted mismo. Vuelve en uno o dos años y echa un vistazo ...
- Si solo habla sobre el
using namespace std
es posible que no esté al tanto de todas las cosas que toma, y cuando agrega otro#include
o se muda a una nueva revisión de C ++, puede que tenga conflictos de nombre de los que no estaba al tanto.
Puedes usarlo localmente
Adelante y utilízalo localmente (casi) libremente. Esto, por supuesto, le impide la repetición de std::
- y la repetición también es mala.
Un modismo para usarlo localmente.
En C ++ 03 había un modismo, código repetitivo, para implementar una función de swap
para tus clases. Se sugirió que realmente use un local using namespace std
, o al menos using std::swap
:
class Thing {
int value_;
Child child_;
public:
// ...
friend void swap(Thing &a, Thing &b);
};
void swap(Thing &a, Thing &b) {
using namespace std; // make `std::swap` available
// swap all members
swap(a.value_, b.value_); // `std::stwap(int, int)`
swap(a.child_, b.child_); // `swap(Child&,Child&)` or `std::swap(...)`
}
Esto hace la siguiente magia:
- El compilador elegirá
std::swap
paravalue_
, es decir,void std::swap(int, int)
. - Si tiene una sobrecarga
void swap(Child&, Child&)
implementado, el compilador lo elegirá. - Si no tiene esa sobrecarga, el compilador utilizará
void std::swap(Child&,Child&)
e intentará intercambiar estos.
Con C ++ 11 ya no hay razón para usar este patrón. La implementación de std::swap
se cambió para encontrar una sobrecarga potencial y elegirla.
Otros me han dicho que escribir using namespace std
en el código es incorrecto, y que debería usar std::cout
y std::cin
directamente en su lugar.
¿Por qué el using namespace std
una mala práctica? ¿Es ineficiente o corre el riesgo de declarar variables ambiguas (variables que comparten el mismo nombre que una función en el std
nombres std
)? ¿Afecta el rendimiento?
debe poder leer el código escrito por personas que tienen opiniones diferentes de estilos y mejores prácticas que usted.
Si solo estás usando cout, nadie se confunde. Pero cuando tienes muchos espacios de nombres volando y ves esta clase y no estás exactamente seguro de qué es lo que hace, tener el espacio de nombres explícito actúa como una especie de comentario. Puede ver a primera vista, ''oh, esto es una operación del sistema de archivos'' o ''eso es hacer cosas de red''.
Considerar
// myHeader.h
#include <sstream>
using namespace std;
// someoneElses.cpp/h
#include "myHeader.h"
class stringstream { // uh oh
};
Tenga en cuenta que este es un ejemplo simple, si tiene archivos con 20 entradas y otras importaciones, tendrá un montón de dependencias para resolver el problema. Lo peor de esto es que puede obtener errores no relacionados en otros módulos dependiendo de las definiciones que entren en conflicto.
No es horrible, pero se ahorrará dolores de cabeza al no usarlo en los archivos de cabecera o el espacio de nombres global. Probablemente esté bien hacerlo en ámbitos muy limitados, pero nunca he tenido problemas para escribir los 5 caracteres adicionales para aclarar de dónde provienen mis funciones.
El problema de poner el using namespace
de using namespace
en los archivos de encabezado de sus clases es que obliga a cualquier persona que quiera usar sus clases (al incluir sus archivos de encabezado) también a "usar" (es decir, ver todo en) esos otros espacios de nombres.
Sin embargo, puede sentirse libre de poner una declaración de uso en sus archivos (privados) * .cpp.
Tenga en cuenta que algunas personas no están de acuerdo con que yo diga "siéntase libre" de esta manera, ya que aunque una declaración de uso en un archivo cpp es mejor que en un encabezado (porque no afecta a las personas que incluyen su archivo de encabezado), piensan que aún es así. no es bueno (ya que, dependiendo del código, podría hacer que la implementación de la clase sea más difícil de mantener). Este tema de preguntas frecuentes dice:
La directiva de uso existe para el código C ++ heredado y para facilitar la transición a los espacios de nombres, pero probablemente no debería usarlo regularmente, al menos no en su nuevo código C ++.
El FAQ sugiere dos alternativas:
Una declaración de uso:
using std::cout; // a using-declaration lets you use cout without qualification cout << "Values:";
Sólo escribiendo std ::
std::cout << "Values:";
El uso de muchos espacios de nombres al mismo tiempo es obviamente una receta para el desastre, pero usar JUST espacio de nombres std
y solo espacio de nombres std
no es tan importante en mi opinión porque la redefinición solo puede ocurrir por su propio código ...
Entonces, considérelas funciones como nombres reservados como "int" o "class" y eso es todo.
La gente debería dejar de ser tan anal al respecto. Tu profesor tenía razón todo el tiempo. Solo usa UN espacio de nombres; ese es el punto central de usar espacios de nombres en primer lugar. Se supone que no debes usar más de uno al mismo tiempo. A menos que sea el tuyo. Así que de nuevo, la redefinición no va a suceder.
Es bueno ver el código y saber lo que hace. Si veo std::cout
, sé que esa es la secuencia de cout
de la biblioteca std
. Si veo cout
entonces no lo sé. Podría ser la secuencia cout
de la biblioteca std
. O podría haber un int cout = 0;
Diez líneas más altas en la misma función. O una variable static
llamada cout
en ese archivo. Podría ser cualquier cosa.
Ahora tome un código base de un millón de líneas, que no es particularmente grande, y está buscando un error, lo que significa que sabe que hay una línea en este millón de líneas que no hace lo que se supone que debe hacer. cout << 1;
podría leer un cout
static int
llamado static int
, desplazarlo hacia la izquierda un bit y tirar el resultado. Buscando un error, tendría que comprobar eso. ¿Puedes ver cómo realmente prefiero ver std::cout
?
Es una de estas cosas que parece una muy buena idea si usted es profesor y nunca tuvo que escribir y mantener ningún código para ganarse la vida. Me encanta ver el código donde (1) sé lo que hace; y, (2) estoy seguro de que la persona que lo escribió sabía lo que hace.
Esto no está relacionado con el rendimiento en absoluto. Pero considera esto: estás usando dos bibliotecas llamadas Foo y Bar:
using namespace foo;
using namespace bar;
Todo funciona bien, puedes llamar a Blah()
desde Foo y Quux()
desde Bar sin problemas. Pero un día se actualiza a una nueva versión de Foo 2.0, que ahora ofrece una función llamada Quux()
. Ahora tienes un conflicto: tanto Foo 2.0 como Bar importan Quux()
en tu espacio de nombres global. Esto requerirá un poco de esfuerzo para solucionarlo, especialmente si los parámetros de la función coinciden.
Si hubiera usado foo::Blah()
y bar::Quux()
, entonces la introducción de foo::Quux()
no habría sido un evento.
Estoy de acuerdo con todo lo que Greg escribió , pero me gustaría agregar: ¡Incluso puede ser peor de lo que Greg dijo!
Library Foo 2.0 podría introducir una función, Quux()
, que es una mejor opción para algunas de sus llamadas a Quux()
que la bar::Quux()
su código llamó por años. Entonces su código aún se compila , pero silenciosamente llama a la función incorrecta y sabe qué sabe Dios. Eso es tan malo como las cosas pueden llegar.
Tenga en cuenta que el std
nombres std
tiene toneladas de identificadores, muchos de los cuales son muy comunes ( list
reflexión, sort
, string
, iterator
, etc.) que probablemente también aparezcan en otro código.
Si considera que esto es poco probable: hubo una pregunta aquí en en la que casi exactamente sucedió esto (función incorrecta llamada debido a que se omite el prefijo std::
) aproximadamente medio año después de dar esta respuesta. Here hay otro ejemplo más reciente de tal pregunta. Así que este es un problema real.
Aquí hay un punto de datos más: Hace muchos, muchos años, también me resultaba molesto tener que prefijar todo desde la biblioteca estándar con std::
. Luego trabajé en un proyecto en el que se decidió al principio que tanto las directivas como las declaraciones están prohibidas, excepto para los ámbitos de funciones. ¿Adivina qué? A la mayoría de nosotros nos llevó muy pocas semanas acostumbrarnos a escribir el prefijo, y después de unas pocas semanas, la mayoría de nosotros incluso estuvimos de acuerdo en que hacía que el código fuera más legible . Hay una razón para eso: si te gusta la prosa más corta o más larga es subjetivo, pero los prefijos agregan objetivamente claridad al código. No solo el compilador, sino que a usted también le resulta más fácil ver a qué identificador se refiere.
En una década, ese proyecto creció hasta tener varios millones de líneas de código. Dado que estas discusiones surgen una y otra vez, una vez sentí curiosidad por la frecuencia using
que se utilizó el alcance de la función (permitida) en el proyecto. Le pregunté por las fuentes y solo encontré una o dos docenas de lugares donde se usaba. Para mí, esto indica que, una vez que lo intentamos, a los desarrolladores no les resulta lo suficientemente estd std::
suficientemente doloroso como para emplear el uso de directivas, incluso una vez cada 100 kLoC, incluso cuando se permitió su uso.
En pocas palabras: prefijar explícitamente todo no hace ningún daño, requiere muy poco tiempo para acostumbrarse y tiene ventajas objetivas. En particular, hace que el código sea más fácil de interpretar para el compilador y para los lectores humanos, y ese debería ser probablemente el objetivo principal al escribir código.
Estoy de acuerdo en que no se debe usar globalmente, pero no es tan malo utilizarlo localmente, como en un namespace
. Aquí hay un ejemplo de "El lenguaje de programación C ++" :
namespace My_lib {
using namespace His_lib; // everything from His_lib
using namespace Her_lib; // everything from Her_lib
using His_lib::String; // resolve potential clash in favor of His_lib
using Her_lib::Vector; // resolve potential clash in favor of Her_lib
}
En este ejemplo, resolvimos posibles conflictos de nombres y ambigüedades derivadas de su composición.
Los nombres declarados explícitamente allí (incluidos los nombres declarados mediante declaraciones de uso como His_lib::String
) tienen prioridad sobre los nombres accesibles en otro ámbito mediante una directiva using namespace Her_lib
( using namespace Her_lib
).
Los programadores experimentados usan lo que resuelve sus problemas y evitan todo lo que crea nuevos problemas, y evitan las directivas de uso a nivel de archivo de cabecera por esta razón exacta.
Los programadores experimentados también intentan evitar la calificación completa de los nombres dentro de sus archivos fuente. Una razón menor para esto es que no es elegante escribir más código cuando menos código es suficiente a menos que haya buenas razones . Una razón importante para esto es desactivar la búsqueda dependiente de argumentos (ADL).
¿Cuáles son estas buenas razones ? A veces, los programadores quieren desactivar ADL explícitamente, otras veces quieren desambiguar.
Así que lo siguiente está bien:
- Directivas de uso a nivel de función y declaraciones de uso dentro de las implementaciones de funciones
- Declaraciones de uso de nivel de archivo fuente dentro de archivos fuente
- (A veces) directivas de uso de nivel de archivo fuente
No se debe usar la directiva de uso a nivel global, especialmente en los encabezados. Sin embargo, hay situaciones en las que es apropiado incluso en un archivo de encabezado:
template <typename FloatType> inline
FloatType compute_something(FloatType x)
{
using namespace std; //no problem since scope is limited
return exp(x) * (sin(x) - cos(x * 2) + sin(x * 3) - cos(x * 4));
}
Esto es mejor que la calificación explícita ( std::sin
, std::cos
...) porque es más corto y tiene la capacidad de trabajar con tipos de punto flotante definidos por el usuario (a través de la búsqueda dependiente de argumentos).
Otra razón es la sorpresa.
Si veo cout << blah
, en lugar de std::cout << blah
Creo que ¿qué es esto cout
? ¿Es el cout
normal? ¿Es algo especial?
Recientemente me encontré con una queja sobre Visual Studio 2010 . Resultó que casi todos los archivos de origen tenían estas dos líneas:
using namespace std;
using namespace boost;
Muchas de las características de Boost están incorporadas en el estándar C ++ 0x, y Visual Studio 2010 tiene muchas características de C ++ 0x, por lo que de repente estos programas no se estaban compilando.
Por lo tanto, evitando using namespace X;
es una forma de prueba de futuro, una forma de asegurarse de que un cambio en las bibliotecas y / o archivos de encabezado en uso no va a romper un programa.
Se trata de gestionar la complejidad. El uso del espacio de nombres atraerá las cosas que no desee y, por lo tanto, posiblemente dificultará la depuración (lo digo, posiblemente). Usar std :: en todo el lugar es más difícil de leer (más texto y todo eso).
Caballos para cursos: administre su complejidad de la mejor manera que pueda y se sienta capaz.
Si importa los archivos del encabezado derecho, repentinamente tendrá nombres como hex
, left
, plus
o count
en su ámbito global. Esto puede ser sorprendente si no sabe que std::
contiene estos nombres. Si también trata de usar estos nombres localmente, puede causar bastante confusión.
Si todas las cosas estándar están en su propio espacio de nombres, no tiene que preocuparse por las colisiones de nombres con su código u otras bibliotecas.
También lo considero una mala práctica. ¿Por qué? Solo un día pensé que la función de un espacio de nombres es dividir cosas, así que no debería estropearlo con tirar todo en una bolsa global. Sin embargo, si uso a menudo ''cout'' y ''cin'', escribo: using std::cout; using std::cin;
using std::cout; using std::cin;
en el archivo cpp (nunca en el archivo de encabezado, ya que se propaga con #include
). Pienso que nadie cuerdo nombrará nunca una secuencia de cout
o cin
. ;)
Versión corta: no use declaraciones o directivas globales en los archivos de encabezado. Siéntase libre de usarlos en los archivos de implementación. Esto es lo que Herb Sutter y Andrei Alexandrescu tienen que decir sobre este tema en los Estándares de codificación de C ++ (en negrita para enfatizar es mío):
Resumen
Los usos del espacio de nombres son para su conveniencia, no para que pueda infligir a otros: nunca escriba una declaración de uso o una directiva de uso antes de una directiva #include.
Corolario: en los archivos de encabezado, no escriba el nivel de espacio de nombres usando directivas o declaraciones; en su lugar, explícitamente espacios de nombres-calificar todos los nombres. (La segunda regla se sigue de la primera, porque los encabezados nunca pueden saber qué otros encabezados #incluye podrían aparecer después de ellos).
Discusión
En resumen: puede y debe usar el espacio de nombres usando declaraciones y directivas generosamente en sus archivos de implementación después de #incluir directivas y sentirse bien al respecto. A pesar de las repetidas afirmaciones de lo contrario, el espacio de nombres que utiliza declaraciones y directivas no es malo y no anula el propósito de los espacios de nombres. Más bien, son los que hacen que los espacios de nombres sean utilizables .
Estoy de acuerdo con los demás aquí, pero me gustaría abordar las inquietudes relacionadas con la legibilidad: puede evitar todo eso simplemente usando typedefs en la parte superior de su declaración de archivo, función o clase.
Normalmente lo uso en mi declaración de clase, ya que los métodos en una clase tienden a tratar con tipos de datos similares (los miembros) y typedef es una oportunidad para asignar un nombre que sea significativo en el contexto de la clase. Esto realmente ayuda a la legibilidad en las definiciones de los métodos de clase.
//header
class File
{
typedef std::vector<std::string> Lines;
Lines ReadLines();
}
y en la implementación:
//cpp
Lines File::ReadLines()
{
Lines lines;
//get them...
return lines;
}
Opuesto a:
//cpp
vector<string> File::ReadLines()
{
vector<string> lines;
//get them...
return lines;
}
o:
//cpp
std::vector<std::string> File::ReadLines()
{
std::vector<std::string> lines;
//get them...
return lines;
}
Un ejemplo donde el uso de espacio de nombres arroja un error de compilación debido a la ambigüedad del conteo, que también es una función en la biblioteca de algoritmos.
#include <iostream>
using namespace std;
int count = 1;
int main() {
cout<<count<<endl;
}
"¿Por qué es ''utilizando espacio de nombres estándar;'' ¿Se considera una mala práctica en C ++? "
Lo puse al revés: ¿por qué algunos tipos de caracteres adicionales se consideran engorrosos?
Considere, por ejemplo, escribir una pieza de software numérico, ¿por qué incluso consideraría la posibilidad de contaminar mi espacio de nombres global al cortar "general :: vector" general a "vector" cuando "vector" es uno de los conceptos más importantes del dominio del problema?
Con identificadores importados no calificados, necesita herramientas de búsqueda externas como grep para averiguar dónde se declaran los identificadores. Esto hace que el razonamiento sobre la corrección del programa sea más difícil.
Depende de donde se encuentre. Si es un encabezado común, entonces está disminuyendo el valor del espacio de nombres fusionándolo en el espacio de nombres global. Tenga en cuenta que esta podría ser una buena forma de crear módulos globales.
Desde mi experiencia, si tiene varias bibliotecas que usan, por ejemplo cout
, pero para un propósito diferente puede usar el mal cout
.
Por ejemplo, si escribo en, using namespace std;
y using namespace otherlib;
y el tipo simplemente cout (que pasa a ser en ambos), en lugar de std::cout
(o ''otherlib::cout''
), es posible utilizar el equivocado, y obtener errores, es mucho más eficaz y eficiente de usar std::cout
.
Esta es una mala práctica, a menudo conocida como contaminación de espacio de nombres global. Pueden surgir problemas cuando más de un espacio de nombres tiene el mismo nombre de función que la firma, entonces el compilador decidirá de forma ambigua cuál llamar, y todo esto se puede evitar cuando esté especificando el espacio de nombres con su función call std::cout
. Espero que esto ayude. :)
Estoy de acuerdo con los demás: está pidiendo conflictos de nombres, ambigüedades y el hecho es que es menos explícito. Si bien puedo ver el uso de using
, mi preferencia personal es limitarlo. También consideraría fuertemente lo que algunos otros señalaron:
Si desea buscar un nombre de función que pueda ser un nombre bastante común, pero solo desea encontrarlo en el std
espacio de nombres (o al revés, desea cambiar todas las llamadas que NO estén en el espacio de nombres std
, espacio de nombres X
, ...), Entonces, ¿cómo te propones hacer esto? Podría escribir un programa para hacerlo, pero ¿no sería mejor dedicar tiempo a trabajar en su propio proyecto en lugar de escribir un programa para mantener su proyecto?
Personalmente, en realidad no me importa el std::
prefijo. Me gusta más el look que no tenerlo. No sé si eso es porque es explícito y me dice "este no es mi código ... estoy usando la biblioteca estándar" o si es otra cosa, pero creo que se ve mejor. Esto puede ser extraño dado que solo recientemente ingresé a C ++ (usé y sigo haciendo C y otros idiomas por mucho más tiempo y C es mi idioma favorito de todos los tiempos, justo por encima del ensamblaje).
Hay otra cosa, aunque está algo relacionada con lo anterior y lo que otros señalan. Si bien esto puede ser una mala práctica, a veces reservo la std::name
versión estándar de la biblioteca y el nombre para la implementación específica del programa. Sí, de hecho, esto podría morderlo y morderlo con fuerza, pero todo se reduce a que empecé este proyecto desde cero y soy el único programador para ello. Ejemplo: sobrecargo std::string
y lo llamo string
. Tengo adiciones útiles. Lo hice en parte debido a mi tendencia de C y Unix (+ Linux) hacia los nombres en minúsculas.
Además de eso, puedes tener alias de espacio de nombres. Aquí hay un ejemplo de dónde es útil que no se haya mencionado. Uso el estándar C ++ 11 y específicamente con libstdc ++. Bueno, no tiene std::regex
soporte completo . Claro que se compila, pero arroja una excepción en el sentido de que es un error en el extremo del programador. Pero es falta de implementación. Así es como lo resolví. Instale la expresión regular de Boost, vincúlela. Luego, hago lo siguiente para que cuando libstdc ++ se haya implementado por completo, solo necesite eliminar este bloque y el código permanezca igual:
namespace std
{
using boost::regex;
using boost::regex_error;
using boost::regex_replace;
using boost::regex_search;
using boost::regex_match;
using boost::smatch;
namespace regex_constants = boost::regex_constants;
}
No discutiré si es una mala idea o no. Sin embargo, argumentaré que lo mantiene limpio para MI proyecto y al mismo tiempo lo hace específico: es cierto que tengo que usar Boost BUT. Lo estoy usando como libstdc ++ finalmente lo tendrá. Sí, comenzar su propio proyecto y comenzar con un estándar (...) desde el principio va muy lejos con la ayuda del mantenimiento, el desarrollo y todo lo relacionado con el proyecto.
Editar:
Ahora que tengo tiempo, solo para aclarar algo. Realmente no creo que sea una buena idea usar el nombre de una clase / lo que sea en el STL de forma deliberada y más específicamente en lugar de. La cadena es la excepción (ignore la primera, la anterior o la segunda aquí, haga un juego de palabras si es necesario) para mí, ya que no me gustó la idea de ''Cadena''. Tal como está, todavía estoy muy sesgado hacia C y sesgado contra C ++. Los detalles ahorradores, gran parte de lo que trabajo se ajustan a C más (pero fue un buen ejercicio y una buena manera de hacerme a mí mismo. Aprender otro idioma y b. Tratar de no tener menos prejuicios contra objetos / clases / etc. Como de mentalidad menos cerrada, menos arrogante, más aceptando). Pero lo que es útil es lo que algunos ya sugirieron: de hecho, sí uso la lista (es bastante genérico, ¿no es así?),ordenar (lo mismo) para nombrar dos que causaría un choque de nombres si tuviera que hacerusing namespace std;
Por eso, para ese fin, prefiero ser específico, tener el control y saber que si pretendo que sea el uso estándar, tendré que especificarlo. En pocas palabras: no se permite suponer.
Y en cuanto a hacer parte de las expresiones regulares de Boost std
. Lo hago para una futura integración y, una vez más, admito que esto es un prejuicio, no creo que sea tan feo como lo boost::regex:: ...
que de hecho es otra cosa para mí. Hay muchas cosas en C ++ que todavía tengo que aceptar en apariencia y métodos (otro ejemplo: las plantillas variadic versus las args [¡aunque admito que las plantillas variadic son muy útiles!]). Incluso aquellos que sí acepto fueron difíciles Y todavía tengo problemas con ellos.
No creo que sea necesariamente una mala práctica en todas las condiciones, pero debe tener cuidado al usarla. Si está escribiendo una biblioteca, probablemente debería usar los operadores de resolución de alcance con el espacio de nombres para evitar que su biblioteca se tope con otras bibliotecas. Para el código de nivel de aplicación, no veo nada malo en ello.
No empeora el rendimiento de su software o proyecto, la inclusión del espacio de nombres al principio de su código fuente no es mala. La inclusión de la using namespace std
instrucción varía según sus necesidades y la forma en que está desarrollando el software o proyecto.
El namespace std
contiene las funciones y variables estándar de C ++. Este espacio de nombres es útil cuando a menudo usaría las funciones estándar de C ++.
Como se menciona en esta page :
La declaración que usa namespace std generalmente se considera una mala práctica. La alternativa a esta declaración es especificar el espacio de nombres al que pertenece el identificador utilizando el operador de alcance (: :) cada vez que declaramos un tipo.
Y ver esta opinión :
No hay ningún problema en usar el "uso de espacio de nombres" en su archivo fuente cuando hace un uso intensivo del espacio de nombres y está seguro de que nada chocará.
Algunas personas dijeron que es una mala práctica incluir el using namespace std
archivo en sus archivos de origen porque está invocando desde ese espacio de nombres todas las funciones y variables. Cuando desee definir una nueva función con el mismo nombre que otra función contenida en namespace std
, sobrecargará la función y podría producir problemas debido a la compilación o ejecución. No se compilará o ejecutará como esperas.
Como se menciona en esta page :
Aunque la declaración nos evita escribir std :: siempre que deseamos acceder a una clase o tipo definido en el espacio de nombres estándar, importa la totalidad del espacio de nombres estándar al espacio de nombres actual del programa. Tomemos algunos ejemplos para entender por qué esto podría no ser tan bueno.
...
Ahora, en una etapa posterior del desarrollo, deseamos utilizar otra versión de cout que se implemente de forma personalizada en alguna biblioteca llamada "foo" (por ejemplo)
...
Observe cómo hay una ambigüedad, ¿a qué biblioteca apunta Cout? El compilador puede detectar esto y no compilar el programa. En el peor de los casos, el programa aún puede compilar pero llamar a la función incorrecta, ya que nunca especificamos a qué espacio de nombre pertenecía el identificador.
Para responder a tu pregunta, lo veo de esta manera en la práctica: muchos programadores (no todos) invocan el espacio de nombres std. Por lo tanto, uno debe tener el hábito de NO usar cosas que incidan o usen los mismos nombres que están en el espacio de nombres estándar. Se trata de un gran acuerdo, pero no tanto en comparación con el número de posibles palabras coherentes y seudónimos que se pueden encontrar estrictamente.
Quiero decir realmente ... decir "no confíes en que esté presente" es solo hacer que confíes en que NO esté presente. Siempre vas a tener problemas para pedir fragmentos de código y repararlos constantemente. Simplemente mantenga sus cosas definidas por el usuario y prestadas en un alcance limitado como deberían y con MUCHO ahorro de globales (honestamente, los globales deberían ser siempre un último recurso para los propósitos de "compilar ahora, cordura más adelante"). Realmente creo que es un mal consejo de tu profesor porque usar std funcionará tanto para "cout" como para "std :: cout" pero NO usar std solo funcionará para "std :: cout". No siempre tendrás la suerte de escribir todo tu propio código.
NOTA: No se centre demasiado en los problemas de eficiencia hasta que realmente aprenda un poco sobre cómo funcionan los compiladores. Con un poco de experiencia en codificación, no tiene que aprender mucho sobre ellos antes de darse cuenta de lo mucho que pueden generalizar un buen código en algo simple. Tan simple como si escribieras todo en C. El buen código es tan complejo como debe ser.
Un ejemplo concreto para aclarar la inquietud. Imagina que tienes una situación en la que tienes 2 bibliotecas, foo y bar, cada una con su propio espacio de nombres:
namespace foo {
void a(float) { /* does something */ }
}
namespace bar {
...
}
Ahora digamos que usas foo y bar juntos en tu propio programa de la siguiente manera:
using namespace foo;
using namespace bar;
void main() {
a(42);
}
En este punto todo está bien. Cuando ejecutas tu programa, ''hace algo''. Pero luego actualizas la barra y digamos que ha cambiado para ser como:
namespace bar {
void a(float) { /* does something completely different */ }
}
En este punto obtendrá un error de compilación:
using namespace foo;
using namespace bar;
void main() {
a(42); // error: call to ''a'' is ambiguous, should be foo::a(42)
}
Por lo tanto, deberá realizar un mantenimiento para aclarar qué ''a'' quiso decir (es decir foo::a
). Probablemente sea indeseable, pero afortunadamente es bastante fácil (solo agregue foo::
delante de todas las llamadas para a
que el compilador marque como ambiguo).
Pero imagina un escenario alternativo donde la barra cambiara para verse así:
namespace bar {
void a(int) { /* does something completely different */ }
}
En este punto, su llamada a(42)
se une repentinamente a en bar::a
lugar de foo::a
y en lugar de hacer "algo" hace "algo completamente diferente". No hay advertencia del compilador ni nada. Tu programa simplemente comienza a hacer algo completamente diferente que antes.
Cuando usas un espacio de nombres estás arriesgando un escenario como este, por lo que la gente se siente incómoda al usar espacios de nombres. Cuantas más cosas haya en un espacio de nombres, mayor será el riesgo de conflicto, por lo que las personas podrían sentirse aún más incómodas al usar el espacio de nombres estándar (debido a la cantidad de cosas en ese espacio de nombres) que otros espacios de nombres.
En última instancia, se trata de un compromiso entre la capacidad de escritura y la fiabilidad / mantenimiento. La legibilidad también puede influir, pero podría ver argumentos para ello. Normalmente, diría que la confiabilidad y la capacidad de mantenimiento son más importantes, pero en este caso, usted pagará constantemente el costo de la capacidad de escritura por un impacto bastante raro de confiabilidad / mantenimiento. La "mejor" compensación determinará su proyecto y sus prioridades.
Un espacio de nombres es un ámbito con nombre. Los espacios de nombres se utilizan para agrupar declaraciones relacionadas y para mantener separados los elementos separados. Por ejemplo, dos bibliotecas desarrolladas por separado pueden usar el mismo nombre para referirse a diferentes elementos, pero un usuario todavía puede usar ambos:
namespace Mylib{
template<class T> class Stack{ /* ... */ };
/ / ...
}
namespace Yourlib{
class Stack{ /* ... */ };
/ / ...
}
void f(int max) {
Mylib: :Stack<int> s1(max) ; / / use my stack
Yourlib: :Stack s2(max) ; / / use your stack
/ / ...
}
Repetir un nombre de espacio de nombres puede ser una distracción tanto para los lectores como para los escritores. En consecuencia, es posible afirmar que los nombres de un espacio de nombres en particular están disponibles sin una calificación explícita. Por ejemplo:
void f(int max) {
using namespace Mylib; / / make names from Mylib accessible
Stack<int> s1(max) ; / / use my stack
Yourlib: :Stack s2(max) ; / / use your stack
/ / ...
}
Los espacios de nombres proporcionan una herramienta poderosa para la administración de diferentes bibliotecas y diferentes versiones de código. En particular, le ofrecen al programador alternativas de cómo hacer una referencia a un nombre no local.
Fuente: Una descripción general del lenguaje de programación C ++ por Bjarne Stroustrup