2010-12-05 28 views
17

Existen argumentos convincentes againstusing namespace std, entonces ¿por qué se introdujo en el idioma? ¿No derrota using namespace el propósito de los espacios de nombres? ¿Por qué querría escribir alguna vez using namespace? ¿Hay algún problema del que no tenga conocimiento que se resuelva elegantemente en using namespace, tal vez en las líneas del idioma using std::swap o algo así?¿Cuál es el propósito de: "usar el espacio de nombres"?

+11

Menos escribir es un argumento bastante seductora ... – delnan

+0

El concepto de utilizar 'utilizar' está trabajando en todo o en contra del espacio de nombres, pero es allí cuando lo necesites – kenny

+3

Ver también Herb Sutter's ["Migrar a espacios de nombres"] (http://www.gotw.ca/publications/migrating_to_namespaces.htm) –

Respuesta

21

Por un lado, esta es la manera de utilizar sobrecargas de operadores en un espacio de nombres (por ejemplo using namespace std::rel_ops; o using namespace boost::assign;)

brevedad es también un argumento fuerte. ¿Realmente te gustaría escribir y leer std::placeholders::_1 en lugar de _1? Además, cuando escribe código en estilo funcional, utilizará una gran cantidad de objetos en el espacio de nombres std y boost.

Otro uso importante (aunque normalmente uno no importar los espacios de nombres enteros) es permitir argumento dependiente de consulta:

template <class T> 
void smart_swap(T& a, T& b) 
{ 
    using std::swap; 
    swap(a, b); 
} 

Si permuta está sobrecargado por algún tipo de T en el mismo espacio de nombres como T , esto usará esa sobrecarga. Si llamó explícitamente al std::swap, esa sobrecarga no se consideraría. Para otros tipos, esto vuelve a std::swap.

BTW, una declaración/directiva que utiliza no anula el propósito de los espacios de nombres, ya que siempre se puede calificar completamente el nombre en caso de ambigüedad.

+0

+ 1, eso es un artument muy convincente :) –

+2

Personalmente, estoy de acuerdo con "using " es el "using namespace " con el que tengo problemas (con algunas excepciones como rel_ops). –

2

La mayoría de las veces es solo un atajo para escribir código. Puede importar nombres en su contexto adjunto. Normalmente lo restrijo a los archivos .cpp, porque cuando se incluye una directiva using en un archivo .h, contamina todos los archivos en los que está incluido. Otra buena práctica es restringir el using namespace al entorno más envolvente posible, por ejemplo, dentro de una declaración de cuerpo de método. Lo veo como una conveniencia, no más, y similar al espacio de nombres de alias, como por ejemplo:

namespace po = boost::program_options; 

y luego se puede escribir

po::variables_map ... 
0

personas se oponen específicamente a using namespace std; pero no a using namespace BigCorp; o para referirse a std::cout (que está usando el espacio de nombres, simplemente no using, si sabe a qué me refiero). Además, la mayoría de las objeciones a using namespace std están en un archivo de encabezado. En un archivo fuente, donde los efectos se pueden ver inmediatamente, es menos dañino.

Los espacios de nombre son un concepto increíblemente útil que me permite tener una clase llamada Fecha aunque una biblioteca que estoy usando tiene una clase llamada Fecha. Antes de que se agregasen al idioma, teníamos que tener cosas como GCDate y GCString (mi empresa, Gregory Consulting, es anterior a std::string). Hacer uso de espacios de nombres (con o sin la palabra clave using) nos permite a todos escribir un código más limpio y ordenado. Pero cuando tienes que decir Gregcons::string cada vez, pierdes la parte más limpia y ordenada. [Descargo de responsabilidad: en realidad ya no uso mi propia clase de cadenas - imagine algún conflicto de nombres apropiado.] Ese es el atractivo de la declaración using. Manténgalo fuera de los encabezados, no lo aplique al std, y generalmente debe mantenerse fuera de problemas.

+0

Yo diría, no use 'using namespace foo', pero' using foo :: whatever'; eso aplica tanto para nombres estándar como para otros nombres. Por ejemplo, no hay nada de malo con 'using std :: cout' si no se hace en un encabezado. – celtschk

0

Me resulta útil cuando se trabaja con bibliotecas con espacios de nombres profundamente anidados. La biblioteca de Boost es uno de esos ejemplos. Imaging escribiendo boost::numeric::ublas::matrix<double> m en todas partes ...

Lo que hay que evitar es hacer using namespace en un archivo de cabecera, ya que esto tiene el potencial de atornillar really cualquier programa que incluye dicho encabezado. Siempre coloque las declaraciones using namespace en archivos .cpp/.cxx, de modo que esté restringido al alcance del archivo.

+2

pero un alias de espacio de nombres también podría resolver esto. O simplemente puede importar selectivamente 'matrix' solamente. – jalf

+2

O puede usar un typedef, p. Ej. 'typedef boost :: numeric :: ublas :: matrix DoubleMatrix' y use' DoubleMatrix' en el resto de su código. Esa es la belleza/maldición de C++: hay varios enfoques para resolver el mismo problema. – CadentOrange

-1

"Los espacios de nombre permiten agrupar entidades como clases, objetos y funciones bajo un nombre. De esta forma, el alcance global se puede dividir en" sub-ámbitos ", cada uno con su propio nombre, donde identificador es cualquier identificador válido y entidades es el conjunto de clases, objetos y funciones que se incluyen dentro del espacio de nombres"

Más información aquí: http://www.cplusplus.com/doc/tutorial/namespaces/

1

la razón principal por la using namespace se introdujo fue la compatibilidad hacia atrás: Si usted tiene un montón de código pre-espacio de nombres usando muchas de las (funciones pre-estándares) de las funciones y clases de la biblioteca estándar, usted quiere una manera simple de hacer eso código de trabajo con un compilador estándar conforme.

Por cierto, las reglas de búsqueda que dependen de argumentos al menos para C++ 98 significan que se using namespace std::rel_ops no hacer lo que quiera en las plantillas (no sé si esto cambió en una versión posterior de la norma).

Ejemplo:

template<typename T> bool bar(T t) 
{ 
    return t > T(); 
} 

namespace foo 
{ 
    class X {}; 
    bool operator<(X, X); 
} 

using namespace std::rel_ops; 

int main() 
{ 
    X x; 
    bar(x); // won't work: X does not have operator> 
} 

Tenga en cuenta que poner el using namespace en namespace foo no ayudará tampoco.

Sin embargo, el uso de declaraciones en el lugar correcto ayuda:

template<typename T> bool bar(T t) 
{ 
    return t > T(); 
} 

namespace foo 
{ 
    class X {}; 
    bool operator<(X, X); 
    using std::rel_ops::operator>; 
} 

int main() 
{ 
    X x; 
    bar(x); // now works: operator> found per ADL via the using declaration in `namespace foo` 
} 
Cuestiones relacionadas