Utilizzo dello spazio dei nomi std


110

Sembra che ci siano punti di vista diversi sull'uso di "using" rispetto allo spazio dei nomi std.

Alcuni dicono usa ' using namespace std', altri dicono di no ma piuttosto prefissano le funzioni std che devono essere usate con ' std::' mentre altri dicono di usare qualcosa del genere:

using std::string;
using std::cout;
using std::cin;
using std::endl;
using std::vector;

per tutte le funzioni std che devono essere utilizzate.

Quali sono i pro ed i contro di ognuno?




Risposte:


131

La maggior parte degli utenti di C ++ è abbastanza contenta di leggere std::string, std::vectorecc. In effetti, vedere un raw vectormi fa chiedere se questo sia il std::vectoro un diverso definito dall'utente vector.

Sono sempre contrario all'uso using namespace std;. Importa tutti i tipi di nomi nello spazio dei nomi globale e può causare tutti i tipi di ambiguità non ovvie.

Di seguito sono riportati alcuni identificatori comuni presenti nello stdspazio dei nomi: count, sort, find, equal, reverse. Avere una variabile locale chiamata countsignifica che using namespace stdnon ti consentirà di usare al countposto di std::count.

Il classico esempio di un conflitto di nomi indesiderato è simile al seguente. Immagina di essere un principiante e di non saperlo std::count. Immagina di utilizzare qualcos'altro <algorithm>o che sia stato inserito da un'intestazione apparentemente non correlata.

#include <algorithm>
using namespace std;

int count = 0;

int increment()
{
    return ++count; // error, identifier count is ambiguous
}

L'errore è in genere lungo e poco amichevole perché std::countè un modello con alcuni tipi nidificati lunghi.

Questo va bene però, perché std::countva nello spazio dei nomi globale e il conteggio delle funzioni lo nasconde.

#include <algorithm>
using namespace std;

int increment()
{
    static int count = 0;
    return ++count;
}

Forse un po 'sorprendentemente, questo è OK. Gli identificatori importati in un ambito dichiarativo vengono visualizzati nello spazio dei nomi comune che racchiude sia il punto in cui sono definiti sia il luogo in cui vengono importati. In altre parole, std::countè visibile come countnello spazio dei nomi globale, ma solo all'interno increment.

#include <algorithm>

int increment()
{
    using namespace std;
    static int count = 0;
    return ++count;
}

E per ragioni simili, countè ambiguo qui. using namespace stdnon causa std::count, nasconde l'esterno countcome ci si potrebbe aspettare. La using namespaceregola significa che std::countappare (nella incrementfunzione) come se fosse stato dichiarato nell'ambito globale, cioè allo stesso ambito int count = 0;e quindi causando l'ambiguità.

#include <algorithm>

int count = 0;

int increment()
{
    using namespace std;
    return ++count; // error ambiguous
}

21
ma digita davvero molto più facilmente senza il prefisso std ::!
xtofl

69
@xtofl: No, non è così. Cinque caratteri non sono così rilevanti durante la digitazione, ma questi cinque caratteri potrebbero essere molto rilevanti durante la lettura. E la facilità di lettura conta molto più della facilità di digitazione per il codice sorgente, poiché il codice è molto più letto che scritto.
sbi

3
Si potrebbe aggiungere che l'istruzione using si comporta correttamente con le regole di ambito.
Martin York

2
@ Martin York: aggiornato con esempi che illustrano le regole di scoping. @Michael Burr: Probabilmente non è così male, quello che davvero non mi piace è dove i messaggi di errore per errori semplici diventano molto più difficili da interpretare, o dove non si verificano affatto. Ad esempio, se si ritiene che una funzione sia nell'ambito, ma non lo è e una funzione std :: lo è, invece di ottenere un utile errore di "identificatore non riconosciuto", spesso si finisce con un argomento più oscuro "impossibile convertire Errore di stile X "o" impossibile generare la funzione dal modello ". Peggio è se una funzione sbagliata viene chiamata silenziosamente. È raro, ma succede.
CB Bailey

5
Ebbene, sono sorpreso che nessuno abbia discusso dell'opzione di using std::xxx;. Non copyinquina lo spazio dei nomi, scrivere codice sarà più breve e penso sia molto più leggibile di std::copy.
legends2k

41

Escludendo le basi (dover aggiungere std :: davanti a tutti gli oggetti / funzioni stl e meno possibilità di conflitto se non si ha "using namespace std")

Vale anche la pena notare che non dovresti mai mettere

using namespace std

In un file di intestazione, poiché può propagarsi a tutti i file che includono quel file di intestazione, anche se non vogliono utilizzare quello spazio dei nomi.

In alcuni casi è molto utile usare cose come

using std::swap

Come se ci fosse una versione specializzata di swap, il compilatore la userà, altrimenti ricadrà su std::swap.

Se chiami std::swap, utilizzi sempre la versione base, che non chiamerà la versione ottimizzata (se esiste).


10
+1 per aver menzionato using std::swap(che è l'unica cosa che io abbia mai usato).
sbi

1
+1 per aver menzionato che u n spuò propagarsi. Solo per notare che può anche penetrare nelle intestazioni costruite correttamente: devono solo essere incluse dopo un'intestazione canaglia.
quamrana

1
Ma se stai definendo una specializzazione swapor move(or hash, lessecc.), Dovresti comunque inserire quella specializzazione namespace std. Ad esempio:namespace std {template<> class hash<X> {public: size_t operator()(const X&) const};} class X: {friend size_t std::hash<X>::operator()(const X&)};
AJMansfield

28

Innanzitutto, un po 'di terminologia:

  • dichiarazione-d'uso : using std::vector;
  • using-Directive : using namespace std;

Penso che l'uso delle direttive using vada bene, purché non vengano utilizzate nell'ambito globale in un file di intestazione. Quindi avere

using namespace std;

nel tuo file .cpp non è davvero un problema e, se risulta essere, è completamente sotto il tuo controllo (e può anche essere limitato a blocchi particolari, se lo desideri). Non vedo alcun motivo particolare per ingombrare il codice con una sfilza di std::qualificatori: diventa solo un mucchio di rumore visivo. Tuttavia, se non stai utilizzando un sacco di nomi dal filestd spazio nomi nel tuo codice, non vedo alcun problema anche nel tralasciare la direttiva. È una tautologia: se la direttiva non è necessaria, non è necessario usarla.

Allo stesso modo, se riesci a cavartela con alcune dichiarazioni using (invece di direttive using ) per tipi specifici nello stdspazio dei nomi, non c'è motivo per cui non dovresti avere solo quei nomi specifici portati nello spazio dei nomi corrente. Allo stesso modo, penso che sarebbe folle e una seccatura per la contabilità avere 25 o 30 dichiarazioni d'uso quando una singola direttiva d'uso farebbe altrettanto bene.

È anche utile tenere presente che ci sono momenti in cui è necessario utilizzare una dichiarazione di utilizzo. Fare riferimento all '"Item 25: Considerate support for a non-throwing swap" di Scott Meyers da Effective C ++, Third Edition. Per fare in modo che una funzione generica basata su modelli utilizzi il metodo di scambio "migliore" per un tipo parametrizzato, è necessario utilizzare una dichiarazione using e una ricerca dipendente dall'argomento (alias ADL o ricerca Koenig):

template< typename T >
void foo( T& x, T& y)
{
    using std::swap;     // makes std::swap available in this function

    // do stuff...

    swap( x, y);         // will use a T-specific swap() if it exists,
                         //  otherwise will use std::swap<T>()

    // ...
 }

Penso che dovremmo esaminare gli idiomi comuni per varie lingue che fanno un uso significativo degli spazi dei nomi. Ad esempio, Java e C # utilizzano gli spazi dei nomi in larga misura (probabilmente più del C ++). Il modo più comune in cui i nomi all'interno degli spazi dei nomi vengono usati in quei linguaggi è portarli in massa nell'ambito corrente con l'equivalente di una direttiva using. Ciò non causa problemi diffusi e le poche volte in cui si tratta di un problema vengono gestiti in base a "eccezioni" trattando i nomi in questione tramite nomi completi o mediante aliasing, proprio come si può fare in C ++.

Herb Sutter e Andrei Alexandrescu hanno questo da dire in "Item 59: Don't write namespace usings in a header file or before an #include" of their book, C ++ Coding Standards: 101 Rules, Guidelines, and Best Practices:

In breve: puoi e dovresti usare lo spazio dei nomi usando le dichiarazioni e le direttive liberamente nei tuoi file di implementazione dopo le #includedirettive e sentirti bene al riguardo. Nonostante ripetute affermazioni contrarie, le dichiarazioni e le direttive che utilizzano lo spazio dei nomi non sono malvagi e non annullano lo scopo degli spazi dei nomi. Piuttosto, sono ciò che rende utilizzabili gli spazi dei nomi.

Stroupstrup è spesso citato come dicendo: "Non inquinare lo spazio dei nomi globale", in "The C ++ Programming Language, Third Edition". Lo dice infatti (C.14 [15]), ma fa riferimento al capitolo C.10.1 dove dice:

Una dichiarazione using aggiunge un nome a un ambito locale. Una direttiva using non lo fa; semplicemente rende i nomi accessibili nell'ambito in cui sono stati dichiarati. Per esempio:

namespaceX {
    int i , j , k ;
}

int k ;
void f1()
{
    int i = 0 ;

    using namespaceX ; // make names from X accessible

    i++; // local i
    j++; // X::j
    k++; // error: X::k or global k ?

    ::k ++; // the global k

    X::k ++; // X’s k
}

void f2()
{
    int i = 0 ;

    using X::i ; // error: i declared twice in f2()
    using X::j ;
    using X::k ; // hides global k

    i++;
    j++; // X::j
    k++; // X::k
}

Un nome dichiarato localmente (dichiarato da una dichiarazione ordinaria o da una dichiarazione di utilizzo) nasconde dichiarazioni non locali con lo stesso nome e qualsiasi sovraccarico illegale del nome viene rilevato al momento della dichiarazione.

Nota l'errore di ambiguità per k++in f1(). Ai nomi globali non viene data la preferenza rispetto ai nomi degli spazi dei nomi resi accessibili nell'ambito globale. Ciò fornisce una protezione significativa contro i conflitti di nome accidentali e, cosa importante, garantisce che non ci siano vantaggi da ottenere dall'inquinamento dello spazio dei nomi globale.

Quando le librerie che dichiarano molti nomi sono rese accessibili tramite le direttive using, è un vantaggio significativo che i conflitti di nomi inutilizzati non siano considerati errori.

...

Spero di vedere una riduzione radicale nell'uso dei nomi globali nei nuovi programmi che utilizzano spazi dei nomi rispetto ai tradizionali programmi C e C ++. Le regole per gli spazi dei nomi sono state create appositamente per non dare vantaggi a un utente "pigro" di nomi globali rispetto a qualcuno che si prende cura di non inquinare l'ambito globale.

E come si ha lo stesso vantaggio di un "utente pigro di nomi globali"? Sfruttando la direttiva using, che rende in modo sicuro i nomi in uno spazio dei nomi disponibili per l'ambito corrente.

Si noti che c'è una distinzione: i nomi nello stdspazio dei nomi resi disponibili a un ambito con l'uso corretto di una direttiva using (inserendo la direttiva dopo #includes) non inquinano lo spazio dei nomi globale. Sta solo rendendo quei nomi disponibili facilmente e con una protezione continua contro gli scontri.


Per quanto riguarda il tuo ultimo punto: Java e C # hanno anche spazi dei nomi molto più ordinati. Se tutto nella BCL fosse in System, "usare System" causerebbe tanti problemi quanto "usare namespace std".
Jeff Hardy

Ma i programmi Java e C # che vedo in genere portano tutti gli spazi dei nomi che usano, non solo "System" (o il suo equivalente). Quindi, invece di una singola direttiva using che include tutti i nomi utilizzati, ce ne sono 5 o 10 che fanno più o meno la stessa cosa. Inoltre, "using namespace std;" causare davvero così tanti problemi?
Michael Burr

Il problema è che std ha troppi nomi comuni e che includere un'intestazione standard potrebbe includere tutti gli altri. Non abbiamo un buon controllo su ciò che viene importato, ci sono troppi rischi. Non ne so abbastanza di Java e C #, ma so di Ada che ha un sistema di moduli di gran lunga migliore di C ++ e dove l'importazione di nomi è solitamente disapprovata. In generale, è prima una questione di convenzione di denominazione (ho visto persone che usano il prefisso e lo spazio dei nomi, non importare non ha senso) quindi di stile.
AProgrammer

1
Non sono ancora convinto che questo sia un problema del mondo reale. Vedo che le direttive di utilizzo vengono utilizzate tutto il tempo senza gravi inconvenienti. Poi di nuovo, non ho problemi a non usarli. Preferisco solo che i std::qualificatori non ingombrino il codice - ci sono altri modi per evitarlo (le dichiarazioni using o i typedef di solito fanno il trucco).
Michael Burr

1
@AProgrammer: dici, "list è un identificatore naturale per identificare l'elenco in un interprete lisp" - ma avere la using namespace std;direttiva " " non ti impedisce di dichiarare il tuo identificatore naturale ' list' - è solo che se lo fai, non puoi uso più lungo std::listsenza qualificarlo. Non è diverso che se non esiste una using namespace std;direttiva " ". Oppure mi sfugge qualcosa?
Michael Burr

17

Non utilizzare mai utilizzando lo spazio dei nomi nell'ambito globale in un file di intestazione. Ciò può portare a conflitti e la persona responsabile del file in cui compare il conflitto non ha alcun controllo sulla causa.

Nel file di implementazione, le scelte sono molto meno ben definite.

  • Mettere uno std using dello spazio dei nomi porta tutti i simboli da quegli spazi dei nomi. Questo può essere problematico poiché quasi nessun corpo conosce tutti i simboli che ci sono (quindi avere una politica di assenza di conflitto è impossibile da applicare nella pratica) senza parlare dei simboli che verranno aggiunti. E lo standard C ++ consente a un'intestazione di aggiungere simboli da altre intestazioni (quello C non lo consente). Può ancora funzionare bene in pratica per semplificare la scrittura in caso controllato. E se si verifica un errore, viene rilevato nel file che presenta il problema.

  • Mettere usando std :: name; ha il vantaggio della semplicità di scrittura senza il rischio di importare simboli sconosciuti. Il costo è che devi importare esplicitamente tutti i simboli desiderati.

  • La qualificazione esplicita aggiunge un po 'di confusione, ma penso che sia meno problematico un po' di pratica.

Nel mio progetto, utilizzo una qualificazione esplicita per tutti i nomi, accetto di usare std :: name, combatto contro l'uso dello spazio dei nomi std (abbiamo un interprete lisp che ha il suo tipo di lista e quindi il conflitto è una cosa sicura).

Per altri spazi dei nomi, è necessario tenere in considerazione anche le convenzioni di denominazione utilizzate. Conosco un progetto che usa lo spazio dei nomi (per il controllo delle versioni) e il prefisso sui nomi. Fare un using namespace Xallora è quasi senza rischi e non farlo porta a codice dall'aspetto stupido PrefixNS::pfxMyFunction(...).

In alcuni casi si desidera importare i simboli. std :: swap è il caso più comune: importi std :: swap e poi usi swap non qualificato. La ricerca dipendente dall'argomento troverà uno scambio adeguato nello spazio dei nomi del tipo se ce n'è uno e tornerà al modello standard se non ce n'è.


Modificare:

Nei commenti, Michael Burr si chiede se i conflitti si verificano nel mondo reale. Ecco un vero esempio dal vivo. Abbiamo una lingua di estensione con è un dialetto lisp. Il nostro interprete ha un file include, lisp.h contenente

typedef struct list {} list;

Abbiamo dovuto integrare e adattare del codice (che chiamerò "motore") che assomigliava a questo:

#include <list>
...
using std::list;
...
void foo(list const&) {}

Quindi abbiamo modificato in questo modo:

#include <list>

#include "module.h"
...
using std::list;
...
void foo(list const&) {}

Buona. Tutto funziona. Alcuni mesi dopo, "module.h" è stato modificato per includere "list.h". I test sono stati superati. "modulo" non era stato modificato in un modo che influisse sulla sua ABI, quindi la libreria "motore" poteva essere usata senza ricompilare i suoi utenti. I test di integrazione erano OK. Pubblicato il nuovo "modulo". La successiva compilazione del motore si è interrotta quando il suo codice non è stato modificato.


1
Uno dei casi controllati in cui penso che l'uso dello spazio dei nomi sia accettabile è nella pubblicazione del codice. La semplificazione facilita l'impaginazione della pagina e aiuta a concentrarsi sul punto esposto. Lo svantaggio è che non mostra davvero una buona pratica, quindi non lo userei nei libri per principianti.
AProgrammer

1
Penso che digitare std :: sia un piccolo prezzo da pagare per la chiarezza
paoloricardo

4
@paoloricardo: D'altra parte, penso che avere std :: show ovunque sia un disordine visivo non necessario.
Michael Burr

1
@Michael: paghi i tuoi soldi e fai la tua scelta!
paoloricardo

2
Grazie per aver dedicato del tempo ad aggiungere i dettagli del problema che hai riscontrato.
Michael Burr

4

Se non hai il rischio di conflitti di nome nel tuo codice con std e altre librerie puoi usare:

using namespace std;

Ma se vuoi conoscere con precisione la dipendenza del tuo codice per la documentazione o c'è il rischio di conflitti di nome usa l'altro modo:

using std::string;
using std::cout;

La terza soluzione, non utilizzare queste soluzioni e scrivere std :: prima di ogni utilizzo nel codice ti offre maggiore sicurezza ma, forse un po 'di pesantezza nel codice ...


4

Tutti e due

using std::string;

e

using namespace std;

aggiungere alcuni simboli (uno o molti) allo spazio dei nomi globale. E l'aggiunta di simboli allo spazio dei nomi globale è qualcosa che non dovresti mai fare nei file di intestazione. Non hai alcun controllo su chi includerà la tua intestazione, ci sono molte intestazioni che includono altre intestazioni (e intestazioni che includono intestazioni che includono intestazioni e così via ...).

Nei file di implementazione (.cpp) sta a te (ricordati di farlo solo dopo tutte le direttive #include). Puoi interrompere solo il codice in questo file specifico, quindi è più facile da gestire e scoprire il motivo del conflitto di nomi. Se preferisci usare std :: (o qualsiasi altro prefisso, ci possono essere molti spazi dei nomi nel tuo progetto) prima degli identificatori, va bene. Se ti piace aggiungere identificatori che usi allo spazio dei nomi globale, va bene. Se vuoi portare l'intero spazio dei nomi sulla tua testa :-), dipende da te. Sebbene gli effetti siano limitati a una singola unità di compilazione, è accettabile.


3

Per me, preferisco usare ::quando possibile.

std::list<int> iList;

Odio scrivere:

for(std::list<int>::iterator i = iList.begin(); i != iList.end(); i++)
{
    //
}

Si spera che con C ++ 0x scriverei questo:

for(auto i = iList.begin(); i != iList.end(); i++)
{
    //
}

Se lo spazio dei nomi è molto lungo,

namespace dir = boost::filesystem;

dir::directory_iterator file("e:/boost");
dir::directory_iterator end;

for( ; file != end; file++)
{
    if(dir::is_directory(*file))
        std::cout << *file << std::endl;
}

@AraK: namespace dir = boost :: filesystem; Immagino che questo sia un alias?
paoloricardo

@paoloricardo: Sì, questo è quello che è.
sbi

2
Gli iteratori dovrebbero essere incrementati con ++i, non i++perché, se è anche definito, crea una copia temporanea non necessaria dell'iteratore.
Felix Dombek

2

Non dovresti mai using namespace stdtrovarti nell'ambito dello spazio dei nomi in un'intestazione. Inoltre, suppongo che la maggior parte dei programmatori si chiederà quando vedrà vectoro stringsenza std::, quindi penso che non using namespace stdsia meglio. Perciò sostengo per non esserlo mai using namespace stdaffatto.

Se ti senti in dovere, aggiungi dichiarazioni using locali come using std::vector. Ma chiediti: quanto vale? Una riga di codice viene scritta una (forse due volte), ma viene letta dieci, cento o mille volte. Lo sforzo di digitazione salvato nell'aggiunta di una dichiarazione o direttiva using è marginale rispetto allo sforzo di lettura del codice.

Con questo in mente, in un progetto dieci anni fa abbiamo deciso di qualificare esplicitamente tutti gli identificatori con i loro nomi completi dello spazio dei nomi. Ciò che all'inizio sembrava imbarazzante divenne routine entro due settimane. Ora, in tutti i progetti di quell'intera azienda nessuno usa più direttive o dichiarazioni. (Con un'eccezione, vedi sotto.) Guardando il codice (diversi MLoC) dopo dieci anni, mi sento come se avessimo preso la decisione giusta.

Ho scoperto che di solito coloro che si oppongono al divieto di usingsolito non lo hanno provato per un progetto. Chi ci ha provato, spesso lo trova meglio che usare direttive / dichiarazioni dopo pochissimo tempo.

Nota: l'unica eccezione è using std::swapche è necessario (specialmente nel codice generico) per raccogliere sovraccarichi swap()che non possono essere inseriti nello stdspazio dei nomi (perché non ci è permesso inserire sovraccarichi di stdfunzioni in questo spazio dei nomi).


3
Una specializzazione di std :: swap sarebbe una specializzazione completa: non è possibile specializzare parzialmente i modelli di funzione. Qualsiasi programma è permesso di specializzarsi in parte qualsiasi modello libreria standard fintanto che la specializzazione dipende da un tipo definito dall'utente.
CB Bailey

@Charles: Sì, hai ragione, ovviamente, non c'è FTPS. E posso specializzare i modelli all'interno std, ma non sovraccaricarli. Mi dispiace per quella brainfart. Correggerò il post.
sbi

2
Non credo che l'intenzione della using namespacedirettiva fosse quella di rendere la digitazione neanche; piuttosto, era per rendere più facile la lettura , perché, come dici tu, quel codice dovrà essere letto decine, centinaia o migliaia di volte. E per alcune persone, legge molto più facilmente con meno std::disordine. Ma questo probabilmente si riduce all'abilità percettiva personale; alcune persone filtrano std::o addirittura ne hanno bisogno come guida (come i serif), altri ci inciampano e si sentono come su una strada sconnessa.
Lumi


1
@sbi: No, non è obiettivo. Dipende dal fatto che tu pensi che std :: sia utile o ingombrante. Più confusione -> meno chiarezza.
Joshua Richardson

2

Gli spazi dei nomi mantengono il codice contenuto per evitare confusione e inquinamento delle firme delle funzioni.

Ecco una demo completa e documentata dell'uso corretto dello spazio dei nomi :

#include <iostream>
#include <cmath>  // Uses ::log, which would be the log() here if it were not in a namespace, see /programming/11892976/why-is-my-log-in-the-std-namespace

// Silently overrides std::log
//double log(double d) { return 420; }

namespace uniquename {
    using namespace std;  // So we don't have to waste space on std:: when not needed.

    double log(double d) {
        return 42;
    }

    int main() {
        cout << "Our log: " << log(4.2) << endl;
        cout << "Standard log: " << std::log(4.2);
        return 0;
    }
}

// Global wrapper for our contained code.
int main() {
    return uniquename::main();
}

Produzione:

Our log: 42
Standard log: 1.43508

1

using namespace stdimporta il contenuto del stdnamespace in quello corrente. Pertanto, il vantaggio è che non sarà necessario digitare std::davanti a tutte le funzioni di quello spazio dei nomi. Tuttavia, può accadere che tu abbia spazi dei nomi diversi con funzioni con lo stesso nome. Quindi, potresti finire di non chiamare quello che desideri.

Specificare manualmente quali si desidera importare stdimpedisce che ciò accada, ma potrebbe risultare in un lungo elenco di utilizzi all'inizio del file, cosa che alcuni sviluppatori troveranno brutta;)!

Personalmente, preferisco specificare lo spazio dei nomi ogni volta che uso una funzione, tranne quando lo spazio dei nomi è troppo lungo, nel qual caso ne metto un po 'using all'inizio del file.

MODIFICA: come notato in un'altra risposta, non dovresti mai inserire un using namespacein un file di intestazione, poiché si propagherà a tutti i file inclusa questa intestazione e quindi potrebbe produrre comportamenti indesiderati.

EDIT2: corretta la mia risposta, grazie al commento di Charles.


2
using namespace std;importa il contenuto dello stdspazio dei nomi nello spazio dei nomi globale. Non cambia lo spazio dei nomi predefinito. La definizione di qualcosa nello spazio dei nomi globale dopo a using namespace stdnon lo inserirà magicamente nello stdspazio dei nomi.
CB Bailey

Scusa, non era questo quello che intendevo. Grazie per averlo fatto notare, correggerò la mia risposta.
Wookai

1
Ragazzi: grazie per le risposte. Sembra che, in generale, sia più sicuro non usare "using namespace std" ed evitare di creare potenziali ambiguità. A conti fatti, l'uso di 'std :: xxx' mi attrae più che dichiarare un elenco delle varie funzioni all'inizio del file sorgente poiché qualifica in modo inequivocabile ciò che è intento.
paoloricardo

1
Citazione (tranne quando lo spazio dei nomi è troppo lungo). Puoi usare l'alias dello spazio dei nomi per aiutarti. 'namespace Rv1 = Thor :: XML :: XPath :: Rules :: Light :: Version1;' Nota gli alias e l'utilizzo di entrambi obbedisce alle regole di ambito;
Martin York

0

Proprio come in Java, dove puoi usare, puoi includere java.util. * O semplicemente selezionare ogni classe individualmente, dipende dallo stile. Nota che non ne vuoi uno using namespace stdall'inizio del tuo file / ampio ambito perché inquinerai lo spazio dei nomi e potresti avere conflitti, sconfiggendo il punto degli spazi dei nomi. Ma se hai una funzione che utilizza molto STL, ingombra il codice per avere un miscuglio di sintassi di prefisso nella tua logica e dovresti probabilmente prendere in considerazione l'uso di using namespace std(quando usi una varietà di classi) o di singoli using(quando usi pochi lezioni spesso).


0

Questa discussione sarà viva finché l'IDE con cui lavori non sarà abbastanza flessibile da mostrare o nascondere le informazioni esatte di cui hai bisogno.

Questo perché l'aspetto che desideri che il tuo codice appaia dipende dall'attività a portata di mano.

Durante la creazione del codice sorgente, preferisco vedere esattamente quale classe sto utilizzando: è std::stringo la BuzFlox::Obs::stringclasse?

Quando si progetta il flusso di controllo, non sono nemmeno interessato ai tipi di variabili, ma desidero concentrarmi su if'se while' e continue's.

Quindi questo è il mio consiglio:

A seconda del pubblico del tuo codice e della potenza dei tuoi strumenti, scegli il modo in cui legge più facilmente o fornisce la maggior parte delle informazioni.


0

Esistono diversi modi per risolverlo.

Primo: usa come hai fatto.

Secondo: fare namespace S = std;, riducendo 2 caratteri.

Terzo: uso static.

Quarto: non usare nomi che stdusi.


-1

Quali sono i pro ed i contro di ognuno

L'unico motivo per tralasciare lo std :: è che potresti, in teoria, reimplementare tutte le funzioni STL da solo. Quindi le tue funzioni potrebbero essere cambiate dall'uso di std :: vector a my :: vector senza cambiare il codice.


Gli spazi dei nomi non sono realmente progettati per consentire la sostituzione di nomi con funzionalità diverse, ma equivalenti. Sono progettati per prevenire conflitti di nomi non intenzionali.
Michael Burr

Sì, quindi l'unica giustificazione per la direttiva "using" che la interrompe è consentirti di cambiare le funzioni in un nuovo spazio dei nomi.
Martin Beckett

Penso che troverai un sacco di programmatori che si lamentano di quanto siano faticosi gli spazi dei nomi e che vogliono buttarli fuori dalla finestra se non ci fosse una direttiva di utilizzo. Per quanto ne so, ogni linguaggio che utilizza gli spazi dei nomi ha qualcosa di simile a una direttiva using per toglierli di mezzo quando li vuoi togliere di mezzo. Se le direttive sono inutili, perché esistono ovunque?
Michael Burr

Penso che l '"utilizzo" fosse inteso a consentire di passare a implementazioni alternative piuttosto che a risparmiare digitando 3 lettere. Mi piace usare "std :: Foo" perché serve come contratto al programmatore che sto usando il normale Foo e non devono controllare. Sono d'accordo che non vorrei dover digitare "com.microsoft.visual-studio.standard-library.numbers.int pippo", alcune delle dichiarazioni dell'iteratore nell'STL si ottengono in questo modo. Python fa un buon lavoro permettendoti di estrarre insiemi di funzioni decorati o non decorati dai moduli.
Martin Beckett

-1

Perché no, ad esempio

typedef std::vector<int> ints_t;
ints_t ints1;
....
ints_t ints2;

invece che ingombrante

std::vector<int> ints1;
...
std::vector<int> ints2;

Lo trovo molto più leggibile ed è il mio standard per la codifica.

Puoi persino usarlo per includere alcune informazioni semantiche per il lettore. Ad esempio, considera i prototipi di funzione

void getHistorgram(std::vector<unsigned int>&, std::vector<unsigned int>&);

quali sono il valore di ritorno?

Che ne dici invece

typedef std::vector<unsigned int> values_t;
typedef std::vector<unsigned int> histogram_t;
...
void getHistogram(values_t&, histogram_t&); 
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.