Che cos'è l'inquinamento "using namespace"?

9

Stavo consultando la guida alla codifica di google [here] e non consiglio di usare lo spazio dei nomi using namespace or : function '- se non l'ho interpretato male.

Questo vale anche per std ? cout<< non funziona senza di esso. Questo libro , raccomanda lo stesso. Quindi, come faccio a utilizzare cout<< senza using namespace std; o std::cout<< ?

Qual è il modo consigliato? %codice%? La maggior parte dei libri di testo c ++ insegnano ai principianti con std::cout<< che stanno propagando una scarsa pratica di codifica?

    
posta Lord Loh. 19.04.2014 - 23:01
fonte

6 risposte

12

Mentre leggo lo standard di Google, non puoi usare la direttiva using namespace foo; ovunque. Questa direttiva introduce tutto ciò che è dichiarato nello spazio dei nomi ed è una causa comune di collisioni e comportamento imprevisto. Altri hanno citato uno molto comune: hai il tuo metodo max o min da qualche parte e collide in un file src dove qualcuno include un'intestazione con il tuo metodo e poi dice using namespace std;

In determinati luoghi, è consentito avere una dichiarazione using, che è nella forma using ::foo::bar;

Le persone amano usare le direttive nel loro codice perché risparmiano un sacco di digitazione, ma corrono rischi. Se hai un file con molte affermazioni cout, posso capire di non voler digitare std :: cout un centinaio di volte, ma puoi semplicemente dire usando :: std :: cout. Considero questi come dichiarazioni variabili: individuali dove sono necessari. Se una funzione in un file di 10 deve scrivere un output, non dichiarare il cout way in alto, metterlo in quella funzione che sta facendo l'output effettivo.

#include <ostream>
//using namespace std; // NO!
//using ::std::cout;   // less bad than using namespace, but I prefer to scope it

int main(int argc, char** argv)
{
   int rc = do_some_stuff(argc, argv);
   using ::std::endl;
   if (rc) { // print the success report
      using ::std::cout;
      cout << "The test run completed. The return code was " << rc << '.' << endl;
    } else {
      using ::std::cerr;
      cerr << "Unable to complete the test run." << endl;
    }
    return 0 == rc;
}

È un po 'estremo con solo un paio di righe in uscita, ma tu hai l'idea.

Un'altra cosa che si può fare è alias o typedef per minimizzare la digitazione. Non trovo std :: qualunque sia così male, ma abbiamo un enorme set di sorgenti con diverse dozzine di moduli e a volte dobbiamo scrivere codice come console_gui::command_window::append("text") . Questo diventa noioso dopo un po 'e causa un sacco di lunghe code. Sono tutto per qualcosa come

typedef console_gui::command_window cw;
cw::append("text");

purché gli alias siano eseguiti in un ambito locale e mantengano un contesto sufficiente per rendere leggibile il codice.

    
risposta data 25.04.2014 - 00:14
fonte
8

Questo perché: 1) sconfigge l'intero scopo dei namespace, che è quello di ridurre la collisione dei nomi; 2) mette a disposizione dello spazio dei nomi globale l'intero spazio dei nomi specificato con la direttiva using.

Ad esempio, se includi e definisci la tua funzione max (), entrerà in collisione con std :: max ().

link

La preferenza è usare std :: member_you_wish_to_use perché dichiara esplicitamente quale spazio dei nomi usare.

    
risposta data 19.04.2014 - 23:42
fonte
5

Citando il link fornito:

You may use a using-declaration anywhere in a .cc file, and in functions, methods or classes in .h files.

// OK in .cc files.

// Must be in a function, method or class in .h files.

using ::foo::bar;

Lo stile di Google vieta di utilizzare l'importazione di spazi dei nomi nel contesto globale, ma consente di farlo in quelli locali.

Ovunque dove usare la dichiarazione interessa solo una porzione di codice limitata e chiaramente visibile, è perfettamente accettabile.

Quando si inquina il contesto globale, il codice non correlato è interessato (implicitamente usando l'intestazione). Non succede nulla quando lo fai nel contesto locale.

    
risposta data 20.04.2014 - 06:56
fonte
1

they do not recommend that one use the using namespace ornamespace:function' - if I did not misinterpret it.

L'hai fatto. La mancata raccomandazione si applica solo alla direttiva using namespace (che è comunemente chiamata abusing namespace , non interamente umoristicamente). È strongmente preferibile utilizzare il nome completo di una funzione o di un oggetto, come std::cout .

    
risposta data 20.04.2014 - 06:25
fonte
1

Sebbene la domanda abbia già risposte utili, un dettaglio sembra essere troppo breve.

La maggior parte dei programmatori è inizialmente un po 'confusa con la parola chiave using e le descrizioni di namespace di utilizzo, anche se cercano di apprenderla cercando il riferimento, perché dichiarazione e direttiva legge in modo un po 'equivalente, entrambe sono parole lunghe relativamente astratte che iniziano con d .

Gli identificatori all'interno dei namespace sono accessibili nominando esplicitamente lo spazio dei nomi:

myNamespace::myIdent

questo potrebbe essere più chiavi da digitare. Ma può anche diminuire il significato del tuo codice, se la maggior parte degli identificatori viene anteposta allo stesso modo. La parola chiave using aiuta a prevenire questi aspetti negativi del namespace. Poiché using funziona a livello di compilatore (non è una macro), il suo effetto dura per l'intero ambito in cui viene utilizzato. Ecco perché lo stile di Google limita il suo utilizzo a ambiti ben definiti, ovvero classi di file di intestazione o funzioni nei file cpp.

... ovviamente c'è una differenza tra usando la dichiarazione

using myNamespace::myIdent; // make myIdent an alias of myNamespace::myIdent

e utilizzando la direttiva

using myNamespace; // make all identifiers of myNamespace directly accessible

Se usato in ambiti enormi, quest'ultimo porta a molto più confusione.

    
risposta data 21.11.2014 - 14:01
fonte
0

Ecco qua:

#include <iostream>

int main()
{
    std::endl(std::operator<<(std::cout, "Hello world!"));
}

Scrivendo in questo modo, evitiamo l'ADL soggetta a errori e usiamo direttive e dichiarazioni.

Questa è una risposta sarcastica. :-D

Sono con Herb Sutter su Google su questo. Dagli standard di codifica C ++:

You can and should use namespace using declarations and directives liberally in your implementation files after #include directives and feel good about it. Despite repeated assertions to the contrary, namespace using declarations and directives are not evil and they do not defeat the purpose of namespaces. Rather, they are what make namespaces usable.

Puoi ossessionarti su potenziali conflitti nello spazio dei nomi che probabilmente non si manifesteranno mai e probabilmente non saranno difficili da risolvere in un evento così astronomicamente raro evitando attentamente le direttive using e specificando esplicitamente ogni cosa che usi (fino al operatori) con dichiarazioni using , o semplicemente andare avanti e avviare using namespace std . Raccomando quest'ultimo da un punto di vista della produttività.

Most c++ text books teach beginners with using namespace std; are they propagating poor coding practice?

Il contrario se me lo chiedi, e credo che Sutter sia d'accordo.

Ora, nel corso della mia carriera, ho riscontrato circa 3 conflitti nello spazio dei nomi come risultato diretto di using di direttive in codebase che coprono decine di milioni di LOC. Tuttavia, in tutti e 3 i casi, si trovavano in file di origine che coprivano oltre 50.000 righe di codice legacy, originariamente scritte in C e poi imbastardite in C ++, che eseguivano un elenco eclettico di funzioni disparate, incluse intestazioni da una dozzina di librerie diverse e un elenco epico di #includes che si estende su una pagina. Nonostante il pasticcio epico, non erano troppo difficili da sistemare poiché causavano errori di compilazione su OSX (l'unico sistema operativo in cui il codice non è riuscito a creare), non bug di runtime. Non organizzare il tuo codice in questo modo da incubo e dovresti stare bene.

Detto questo, evita entrambe using di direttive e dichiarazioni nei file di intestazione. È semplicemente ritardato. Ma per i file di origine e in particolare quelli che non hanno una pagina intera piena di direttive #include , direi di non preoccuparti se non lavori per Google.

    
risposta data 10.12.2017 - 20:43
fonte

Leggi altre domande sui tag