Usando o namespace std

110

Parece haver diferentes visões sobre o uso de 'using' em relação ao namespace std.

Alguns dizem usar ' using namespace std', outros dizem que não, mas prefixam funções std que devem ser usadas com ' std::', enquanto outros dizem que use algo assim:

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

para todas as funções std que devem ser usadas.

Quais são os prós e os contras de cada um?

paoloricardo
fonte

Respostas:

131

A maioria dos usuários de C ++ gosta de ler std::string, std::vectoretc. Na verdade, ver um raw vectorme faz pensar se este é o std::vectorou um diferente definido pelo usuáriovector .

Eu sempre sou contra usar using namespace std; . Ele importa todos os tipos de nomes para o namespace global e pode causar todos os tipos de ambigüidades não óbvias.

Aqui estão alguns identificadores comuns que estão no stdnamespace: contagem, classificação, localização, igual, reverso. Ter uma variável local chamada countsignifica que using namespace stdnão permitirá que você use em countvez de std::count.

O exemplo clássico de um conflito de nome indesejado é algo como o seguinte. Imagine que você é um iniciante e não conhece std::count. Imagine que você está usando algo diferente <algorithm>ou que foi puxado por um cabeçalho aparentemente não relacionado.

#include <algorithm>
using namespace std;

int count = 0;

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

O erro costuma ser longo e hostil porque std::count é um modelo com alguns tipos aninhados longos.

Isso está OK, porque std::countvai para o namespace global e a contagem de função o oculta.

#include <algorithm>
using namespace std;

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

Talvez um pouco surpreendentemente, isso está OK. Os identificadores importados para um escopo declarativo aparecem no namespace comum que inclui tanto onde são definidos quanto para onde são importados. Em outras palavras, std::counté visível como countno namespace global, mas apenas dentro increment.

#include <algorithm>

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

E por razões semelhantes, counté ambíguo aqui. using namespace stdnão causa std::count, esconda o exterior countcomo seria de esperar. A using namespaceregra significa que std::countparece (na incrementfunção) como se tivesse sido declarada no escopo global, ou seja, no mesmo escopo int count = 0;e, portanto, causando a ambigüidade.

#include <algorithm>

int count = 0;

int increment()
{
    using namespace std;
    return ++count; // error ambiguous
}
CB Bailey
fonte
21
mas digita muuuuito mais fácil sem o prefixo std ::!
xtofl
69
@xtofl: Não, não importa. Cinco caracteres não são tão relevantes ao digitar, mas esses cinco caracteres podem ser muito relevantes durante a leitura. E a facilidade de leitura conta muito mais do que a facilidade de digitação do código-fonte, pois o código é muito mais lido do que escrito.
sbi
3
Você poderia acrescentar que a instrução using se comporta corretamente com as regras de escopo.
Martin York
2
@Martin York: Atualizado com exemplos que ilustram as regras de escopo. @Michael Burr: Isso, sem dúvida, não é tão ruim, o que eu realmente não gosto é onde as mensagens de erro para erros simples ficam muito mais difíceis de interpretar, ou onde eles nem acontecem. Por exemplo, se se acredita que uma função está no escopo, mas não está e uma std :: function está, em vez de obter um erro útil de 'identificador não reconhecido', você geralmente acaba com um argumento mais obscuro 'não consegue converter Erro de estilo X 'ou' incapaz de gerar função a partir do modelo '. Pior é se uma função errada for chamada silenciosamente. É raro, mas acontece.
CB Bailey
5
Bem, estou surpreso que ninguém tenha discutido sobre a opção de using std::xxx;. Ele não polui o espaço de nomes, escrever código será mais curto e acho que copyé muito mais legível do que std::copy.
legends2k
41

Excluindo o básico (ter que adicionar std :: na frente de todos os objetos / funções stl e menos chance de conflito se você não tiver 'using namespace std')

Também é importante notar que você nunca deve colocar

using namespace std

Em um arquivo de cabeçalho, pois ele pode se propagar para todos os arquivos que incluem esse arquivo de cabeçalho, mesmo se eles não quiserem usar esse namespace.

Em alguns casos, é muito benéfico usar coisas como

using std::swap

Como se houvesse uma versão especializada de swap, o compilador irá usá-la, caso contrário, ele voltará a std::swap .

Se você ligar std::swap, você sempre usará a versão básica, que não chamará a versão otimizada (se houver).

Yacoby
fonte
10
1 para mencionar using std::swap(que é a única coisa que eu sempre uso).
sbi
1
1 por mencionar que u n spode se propagar. Apenas para observar que ele também pode se infiltrar em cabeçalhos construídos corretamente: Eles apenas precisam ser incluídos após um cabeçalho desonesto.
quamrana
1
Mas se você está definindo uma especialização swapou move(ou hash, lessetc.), você deve colocar essa especialização de namespace stdqualquer maneira. Por exemplo: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

Primeiro, algumas terminologias:

  • declaração de uso : using std::vector;
  • using-Directive : using namespace std;

Acho que usar as diretivas de uso é bom, desde que não sejam usadas no escopo global em um arquivo de cabeçalho. Então tendo

using namespace std;

no seu arquivo .cpp não é realmente um problema e, se for o caso, está completamente sob seu controle (e pode até mesmo ter como escopo blocos específicos, se desejado). Não vejo nenhuma razão particular para confundir o código com uma série de std::qualificadores - torna-se apenas um monte de ruído visual. No entanto, se você não estiver usando um monte de nomes dostd namespace em seu código, também não vejo problema em a diretiva. É uma tautologia - se a diretiva não for necessária, não há necessidade de usá-la.

Da mesma forma, se você pode sobreviver com algumas declarações de uso (em vez de diretivas de uso ) para tipos específicos no stdnamespace, então não há razão para que você não deva ter apenas esses nomes específicos trazidos para o namespace atual. Da mesma forma, acho que seria uma loucura e um aborrecimento contábil ter 25 ou 30 declarações de uso quando uma única diretiva de uso faria o mesmo bem.

Também é bom ter em mente que há momentos em que você deve usar uma declaração de uso. Consulte o "Item 25: Considere o suporte para uma troca sem lançamento" de Scott Meyers em Effective C ++, Third Edition. Para que uma função genérica e modelada use o 'melhor' método de troca para um tipo parametrizado, você precisa fazer uso de uma declaração de uso e pesquisa dependente de argumento (também conhecida como pesquisa ADL ou 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>()

    // ...
 }

Acho que devemos olhar para os idiomas comuns para várias linguagens que fazem uso significativo de namespaces. Por exemplo, Java e C # usam namespaces em grande medida (possivelmente mais do que C ++). A forma mais comum pela qual os nomes dentro de namespaces são usados ​​nessas linguagens é trazendo-os para o escopo atual em massa com o equivalente a uma diretiva using. Isso não causa problemas generalizados e, nas poucas vezes em que é um problema, é tratado como uma 'exceção', lidando com os nomes em questão por meio de nomes totalmente qualificados ou por aliasing - exatamente como pode ser feito em C ++.

Herb Sutter e Andrei Alexandrescu têm a dizer isso no "Item 59: Não escreva usos de namespace em um arquivo de cabeçalho ou antes de um #include" de seu livro, Padrões de Codificação C ++: 101 Regras, Diretrizes e Melhores Práticas:

Resumindo: você pode e deve usar o namespace usando declarações e diretivas livremente em seus arquivos de implementação após as #includediretivas e se sentir bem com isso. Apesar das repetidas afirmações em contrário, os namespaces que usam declarações e diretivas não são nocivos e não anulam o propósito dos namespaces. Em vez disso, são eles que tornam os namespaces utilizáveis.

Stroupstrup é frequentemente citado como dizendo, "Não polua o namespace global", em "The C ++ Programming Language, Third Edition". Ele de fato diz isso (C.14 [15]), mas se refere ao capítulo C.10.1 onde diz:

Uma declaração de uso adiciona um nome a um escopo local. Uma diretiva de uso não; ele simplesmente torna os nomes acessíveis no escopo em que foram declarados. Por exemplo:

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
}

Um nome declarado localmente (declarado por uma declaração comum ou por uma declaração de uso) oculta declarações não locais do mesmo nome e quaisquer sobrecargas ilegais do nome são detectadas no ponto da declaração.

Observe o erro de ambiguidade para k++em f1(). Nomes globais não têm preferência sobre nomes de namespaces acessíveis no escopo global. Isso fornece proteção significativa contra conflitos de nomes acidentais e, mais importante, garante que não haja vantagens em poluir o namespace global.

Quando as bibliotecas que declaram muitos nomes se tornam acessíveis por meio de diretivas de uso, é uma vantagem significativa que os confrontos de nomes não usados ​​não sejam considerados erros.

...

Espero ver uma redução radical no uso de nomes globais em novos programas que usam namespaces em comparação com os programas C e C ++ tradicionais. As regras para namespaces foram criadas especificamente para não dar vantagens a um usuário '' preguiçoso '' de nomes globais sobre alguém que toma cuidado para não poluir o escopo global.

E como alguém tem a mesma vantagem de um 'usuário preguiçoso de nomes globais'? Tirando vantagem da diretiva using, que disponibiliza com segurança os nomes em um namespace para o escopo atual.

Observe que há uma distinção - nomes no stdnamespace disponibilizados para um escopo com o uso adequado de uma diretiva using (colocando a diretiva após o #includes) não poluem o namespace global. É apenas disponibilizar esses nomes facilmente e com proteção contínua contra confrontos.

Michael Burr
fonte
Com relação ao seu último ponto: Java e C # também têm namespaces muito mais organizados. Se tudo no BCL vivesse em System, "usar o System" causaria tantos problemas quanto "usar o namespace std".
Jeff Hardy
Mas os programas Java e C # que vejo normalmente trazem todos os namespaces que usam - não apenas "Sistema" (ou seu equivalente). Portanto, em vez de uma única diretiva using que traz todos os nomes usados, há 5 ou 10 que fazem mais ou menos a mesma coisa. Além disso, faz "using namespace std;" realmente causar tantos problemas?
Michael Burr
O problema é que std tem muitos nomes comuns e que incluir um cabeçalho padrão pode incluir todos os outros. Não temos um bom controle do que é importado, são muitos os riscos. Não sei o suficiente sobre Java e C #, mas sei sobre Ada, que tem um sistema de módulos muito melhor do que C ++ e onde a importação de nomes geralmente é desaprovada. Em geral, é primeiro uma questão de convenção de nomenclatura (já vi pessoas usando prefixo e espaço para nome, não importar não faz sentido) e depois de estilo.
AProgrammer
1
Ainda não estou convencido de que este seja um problema do mundo real. Vejo que as diretivas de uso são usadas o tempo todo, sem inconvenientes graves. Então, novamente, não tenho nenhum problema em não usá-los. Eu apenas prefiro que os std::qualificadores não bagunçam o código - há outras maneiras de evitar isso (using-declarations ou typedefs geralmente resolvem).
Michael Burr
1
@AProgrammer: você diz, "lista é um identificador natural para identificar lista em um interpretador lisp" - mas ter a using namespace std;diretiva " " não o impede de declarar seu identificador natural ' list' - é só que se você o fizer, você não pode use mais std::listsem qualificá-lo. Isso não é diferente de se não houver uma using namespace std;diretiva " ". Ou eu estou esquecendo de alguma coisa?
Michael Burr
17

Nunca use o uso de namespace no escopo global em um arquivo de cabeçalho. Isso pode levar a conflitos e o responsável pelo arquivo onde o conflito aparece não tem controle sobre a causa.

No arquivo de implementação, as escolhas são muito menos adequadas.

  • Colocar um usando namespace std traz todos os símbolos desses namespaces. Isso pode ser problemático, pois quase nenhum corpo conhece todos os símbolos que estão lá (portanto, ter uma política de nenhum conflito é impossível de aplicar na prática) sem falar dos símbolos que serão adicionados. E o padrão C ++ permite que um cabeçalho adicione símbolos de outros cabeçalhos (o padrão C não permite isso). Ainda pode funcionar bem na prática para simplificar a escrita em caso controlado. E se ocorrer um erro, ele será detectado no arquivo que apresenta o problema.

  • Colocando usando std :: name; tem a vantagem da simplicidade de escrita sem o risco de importar símbolos desconhecidos. O custo é que você precisa importar explicitamente todos os símbolos desejados.

  • Qualificar explicitamente adiciona um pouco de confusão, mas acho que é menos problemático alguma prática.

No meu projeto, uso qualificação explícita para todos os nomes, aceito usar std :: name, luto contra o uso de namespace std (temos um interpretador lisp que tem seu próprio tipo de lista e, portanto, o conflito é uma coisa certa).

Para outros namespaces, você também deve levar em consideração as convenções de nomenclatura usadas. Eu sei de um projeto que usa namespace (para controle de versão) e prefixo em nomes. Fazer um using namespace Xthen é quase sem risco e não fazer isso leva a um código de aparência estúpida PrefixNS::pfxMyFunction(...).

Existem alguns casos em que você deseja importar os símbolos. std :: swap é o caso mais comum: você importa std :: swap e então usa swap não qualificado. A pesquisa dependente do argumento encontrará uma troca adequada no namespace do tipo, se houver, e retornará ao modelo padrão, se não houver.


Editar:

Nos comentários, Michael Burr questiona se os conflitos ocorrem no mundo real. Aqui está um exemplo real ao vivo. Temos uma linguagem de extensão com um dialeto lisp. Nosso intérprete tem um arquivo de inclusão, lisp.h contendo

typedef struct list {} list;

Tivemos que integrar e adaptar algum código (que chamarei de "motor") que se parecia com isto:

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

Então, nós modificamos assim:

#include <list>

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

Boa. Tudo funciona. Alguns meses depois, "module.h" foi modificado para incluir "list.h". Os testes foram aprovados. "módulo" não foi modificado de uma forma que afetou sua ABI, então a biblioteca "engine" poderia ser usada sem recompilar seus usuários. Os testes de integração correram bem. Novo "módulo" publicado. A próxima compilação do motor quebrou quando seu código não foi modificado.

AProgrammer
fonte
1
Um dos casos controlados em que acho que o uso de namespace é aceitável é na publicação de código. A simplificação facilita o layout da página e ajuda a concentrar-se no ponto exposto. A desvantagem é que ele realmente não mostra uma boa prática, então eu não o usaria em livros para iniciantes.
AProgrammer
1
Acho que digitar std :: é um pequeno preço a pagar pela clareza
paoloricardo
4
@paoloricardo: Por outro lado, acho que ter std :: aparecendo em todos os lugares é uma desordem visual desnecessária.
Michael Burr
1
@Michael: você paga seu dinheiro e faz sua escolha!
paoloricardo
2
Obrigado por adicionar os detalhes do problema que você encontrou.
Michael Burr
4

Se você não corre o risco de conflitos de nome em seu código com std e outras bibliotecas, você pode usar:

using namespace std;

Mas se você quiser saber exatamente a dependência do seu código para documentação ou se houver risco de conflitos de nome, use o outro caminho:

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

A terceira solução, não use essas soluções e escreva std :: antes de cada uso no código traz mais segurança, mas talvez um pouco mais pesado no código ...

Matthieu
fonte
4

Ambos

using std::string;

e

using namespace std;

adicione alguns símbolos (um ou muitos) ao namespace global. E adicionar símbolos ao namespace global é algo que você nunca deve fazer em arquivos de cabeçalho. Você não tem controle sobre quem incluirá seu cabeçalho. Existem muitos cabeçalhos que incluem outros cabeçalhos (e cabeçalhos que incluem cabeçalhos que incluem cabeçalhos e assim por diante ...).

Nos arquivos de implementação (.cpp) depende de você (lembre-se de fazê-lo somente após todas as diretivas #include). Você pode quebrar apenas o código neste arquivo específico, por isso é mais fácil de gerenciar e descobrir o motivo do conflito de nomes. Se você preferir usar std :: (ou qualquer outro prefixo, pode haver muitos namespaces em seu projeto) antes de identificadores, está tudo bem. Se você gosta de adicionar identificadores que usa ao namespace global, tudo bem. Se você quiser colocar todo o namespace em sua cabeça :-), é com você. Embora os efeitos sejam limitados a uma única unidade de compilação, é aceitável.

Tadeusz Kopec
fonte
3

Para mim, prefiro usar ::quando possível.

std::list<int> iList;

Eu odeio escrever:

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

Com sorte, com C ++ 0x eu escreveria isto:

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

Se o namespace for muito longo,

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
fonte
@AraK: namespace dir = boost :: filesystem; Eu acho que isso é um pseudônimo?
paoloricardo
@paoloricardo: Sim, é isso.
sbi
2
Os iteradores devem ser incrementados com ++i, não i++porque, se for definido, crie uma cópia temporária desnecessária do iterador.
Felix Dombek
2

Você nunca deve estar using namespace stdno escopo do namespace em um cabeçalho. Além disso, suponho que a maioria dos programadores se perguntará quando verão vectorou stringnão std::, então acho que não using namespace stdé melhor. Portanto, eu argumento para nunca ser using namespace std.

Se você sentir que deve, adicione local usando declarações como using std::vector. Mas pergunte-se: de que vale isso? Uma linha de código é escrita uma vez (talvez duas vezes), mas é lida dez, cem ou mil vezes. O esforço de digitação economizado ao adicionar uma declaração ou diretiva de uso é marginal em comparação com o esforço de ler o código.

Com isso em mente, em um projeto de dez anos atrás, decidimos qualificar explicitamente todos os identificadores com seus nomes de namespace completos. O que parecia estranho a princípio se tornou rotina em duas semanas. Agora, em todos os projetos de toda aquela empresa ninguém está mais usando diretivas ou declarações. (Com uma exceção, veja abaixo.) Olhando para o código (vários MLoC) depois de dez anos, sinto que tomamos a decisão certa.

Eu descobri que normalmente, aqueles que se opõem ao banimento usinggeralmente não tentaram para um projeto. Aqueles que tentaram, muitas vezes acham melhor do que usar diretivas / declarações depois de um tempo muito curto.

Nota: A única exceção é a using std::swapnecessária (especialmente em código genérico) para coletar sobrecargas de swap()que não podem ser colocadas no stdnamespace (porque não temos permissão para colocar sobrecargas de stdfunções neste namespace).

sbi
fonte
3
Uma especialização de std :: swap seria uma especialização completa - você não pode especializar parcialmente os modelos de função. Qualquer programa tem permissão para especializar parcialmente qualquer modelo de biblioteca padrão, desde que essa especialização dependa de um tipo definido pelo usuário.
CB Bailey
@Charles: Sim, você está certo, claro, não há FTPS. E posso me especializar em modelos std, mas não sobrecarregar. Desculpe por aquele cérebro. Vou corrigir a postagem.
sbi
2
Também não acho que a intenção da using namespacediretiva era fazer digitação ; ao contrário, era para facilitar a leitura , porque, como você diz, esse código terá de ser lido dezenas, centenas ou milhares de vezes. E, para algumas pessoas, é muito mais fácil de ler com menos std::confusão. Mas isso provavelmente se resume à habilidade pessoal de percepção; algumas pessoas filtram std::ou até mesmo precisam dela para orientação (como serifas), outras tropeçam nela e se sentem em uma estrada esburacada.
Lumi
1
@sbi: Não, isso não é objetivo. Depende se você acha que std :: é útil ou desordenado. Mais desordem -> menos clareza.
Joshua Richardson
2

Os namespaces mantêm o código contido para evitar confusão e poluição das assinaturas de função.

Aqui está uma demonstração completa e documentada do uso adequado de namespace :

#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();
}

Resultado:

Our log: 42
Standard log: 1.43508
Cees Timmerman
fonte
1

using namespace stdimporta o conteúdo do stdnamespace para o atual. Portanto, a vantagem é que você não terá que digitar std::antes de todas as funções desse namespace. No entanto, pode acontecer que você tenha namespaces diferentes com funções com o mesmo nome. Assim, você pode acabar não ligando para quem deseja.

Especificar manualmente quais você deseja importar stdevita que isso aconteça, mas pode resultar em uma longa lista de uso no início de seu arquivo, o que alguns desenvolvedores vão achar feio;)!

Pessoalmente, prefiro especificar o namespace cada vez que uso uma função, exceto quando o namespace é muito longo; nesse caso, coloco algum using no início do arquivo.

EDITAR: conforme observado em outra resposta, você nunca deve colocar um using namespaceem um arquivo de cabeçalho, pois ele se propagará para todos os arquivos incluindo este cabeçalho e, portanto, pode produzir um comportamento indesejado.

EDIT2: corrigiu minha resposta, graças ao comentário de Charles.

Wookai
fonte
2
using namespace std;importa o conteúdo do stdnamespace para o namespace global. Isso não muda o namespace padrão. Definir algo no namespace global após um using namespace stdnão irá colocá-lo magicamente no stdnamespace.
CB Bailey
Desculpe, não foi isso que eu quis dizer. Obrigado por apontar isso, corrigirei minha resposta.
Wookai
1
Pessoal: obrigado pelas respostas. Parece que, em geral, é mais seguro não usar 'using namespace std' e evitar a criação de ambiguidades potenciais. Em suma, usar 'std :: xxx' me atrai mais do que declarar uma lista das várias funções no início do arquivo de origem, uma vez que qualifica inequivocamente qual é a intenção de cada um.
paoloricardo
1
Citação (exceto quando o namespace é muito longo). Você pode usar aliasing de namespace para ajudar nisso. 'namespace Rv1 = Thor :: XML :: XPath :: Rules :: Light :: Version1;' Observe os aliases e o uso de ambos obedecem às regras de escopo;
Martin York
0

Muito parecido com Java, onde você pode usar, pode incluir java.util. * Ou simplesmente selecionar cada classe individualmente, isso depende do estilo. Observe que você não quer umusing namespace std no início de seu arquivo / escopo amplo porque poluirá o namespace e possivelmente terá conflitos, anulando o ponto de namespaces. Mas se você tem uma função que usa muito STL, ela bagunça o código para ter uma confusão de sintaxe de prefixação em sua lógica e você provavelmente deve considerar o uso using namespace std(ao usar uma variedade de classes) ou usings individuais (ao usar alguns aulas frequentemente).

Sam Brightman
fonte
0

Esta discussão estará viva enquanto o IDE com o qual você trabalha não for flexível o suficiente para mostrar ou ocultar as informações exatas de que você precisa.

Isso ocorre porque a aparência do seu código depende da tarefa em questão.

Ao criar meu código-fonte, prefiro ver exatamente qual classe estou usando: é std::stringou a BuzFlox::Obs::stringclasse?

Ao projetar o fluxo de controle, nem mesmo estou interessado nos tipos de variáveis, mas quero me concentrar em if'se while' e continue's.

Portanto, este é o meu conselho:

Dependendo do público de seu código e do poder de suas ferramentas, escolha a forma que lê mais facilmente ou fornece mais informações.

xtofl
fonte
0

Existem várias maneiras de consertar isso.

Primeiro: use como você fez.

Segundo: fazer namespace S = std;, reduzindo 2 caracteres.

Terceiro: use static.

Quarto: não use nomes que stdusa.


fonte
-1

Quais são os prós e contras de cada

A única razão para deixar de fora o std :: é que você poderia, em teoria, reimplementar todas as funções STL por conta própria. Então, suas funções podem ser trocadas de std :: vector para my :: vector sem alterar o código.

Martin Beckett
fonte
Os namespaces não foram realmente projetados para permitir a substituição de nomes por funcionalidades diferentes, mas equivalentes. Eles são projetados para evitar conflitos de nomes não intencionais.
Michael Burr
Sim, então a única justificativa para a diretiva 'using' que quebra isso é permitir que você mude funções para um novo namespace.
Martin Beckett
Eu acho que você encontraria muitos programadores reclamando sobre como os namespaces são um saco e querendo jogá-los pela janela se não houvesse uma diretiva de uso. Até onde eu sei, toda linguagem que usa namespaces tem algo semelhante a uma diretiva de uso para tirá-los do caminho quando você quiser. Se as diretivas são inúteis, por que existem em todos os lugares?
Michael Burr
Acho que o "uso" tinha a intenção de permitir que você mudasse para implementações alternativas, em vez de economizar ao digitar 3 letras. Eu gosto de usar "std :: Foo" porque serve como um contrato para o programador que estou usando o Foo normal e eles não precisam verificar. Concordo que não gostaria de ter que digitar "com.microsoft.visual-studio.standard-library.numbers.int foo", algumas das declarações do iterador no STL ficam assim. Python faz um bom trabalho em permitir que você extraia conjuntos de funções decoradas ou não decoradas de módulos.
Martin Beckett
-1

Por que não por exemplo

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

em vez do pesado

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

Acho isso muito mais legível e é meu padrão para codificação.

Você pode até mesmo usá-lo para incluir algumas informações semânticas para o leitor. Por exemplo, considere os protótipos de função

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

quais são o valor de retorno?

Que tal ao invés

typedef std::vector<unsigned int> values_t;
typedef std::vector<unsigned int> histogram_t;
...
void getHistogram(values_t&, histogram_t&); 
ldog
fonte