Eu tenho usado a nova auto
palavra-chave disponível no padrão C ++ 11 para tipos de modelos complicados, e é para isso que acredito que foi projetada. Mas também estou usando para coisas como:
auto foo = std::make_shared<Foo>();
E mais ceticamente para:
auto foo = bla(); // where bla() return a shared_ptr<Foo>
Não vi muita discussão sobre esse tópico. Parece que auto
poderia ser usado em excesso, uma vez que um tipo geralmente é uma forma de documentação e verificações de sanidade. Onde você desenha a linha de uso auto
e quais são os casos de uso recomendados para esse novo recurso?
Para esclarecer: não estou pedindo uma opinião filosófica; Estou solicitando o uso pretendido dessa palavra-chave pelo comitê padrão, possivelmente com comentários sobre como esse uso pretendido é realizado na prática.
Nota lateral: Esta pergunta foi movida para SE.Programmers e depois de volta para Stack Overflow. Discussões sobre isso podem ser encontradas nesta meta questão .
auto
palavra - chave, sabe como ela deve ser usada. É isso que estou perguntando, como alguém que é novo nesse recurso, é como devo usá-lo?var
(ou seja, depois que as pessoas pensavam que não era uma digitação dinâmica, afinal). Se você quiser, pode começar com esta pergunta e fazer as perguntas relacionadas.auto foo = bla();
"ruim" é claramente uma opinião, não um fato, que faz essa pergunta e responde a uma discussão, o que a torna relevante para os Programadores SE, que é exatamente o que indicam os votos próximos. / shrugRespostas:
Acho que se deve usar a
auto
palavra-chave sempre que for difícil dizer como escrever o tipo à primeira vista, mas o tipo do lado direito de uma expressão é óbvio. Por exemplo, usando:para obter o tipo de chave composta
boost::multi_index
, mesmo sabendo que éint
. Você não pode simplesmente escreverint
porque pode ser alterado no futuro. Eu escreveriaauto
neste caso.Portanto, se a
auto
palavra - chave melhorar a legibilidade em um caso específico, use-a. Você pode escreverauto
quando é óbvio para o leitor que tipoauto
representa.aqui estão alguns exemplos:
fonte
bla()
você devolvefoo
.Use em
auto
todos os lugares que puder - particularmenteconst auto
para que os efeitos colaterais sejam menos preocupantes. Você não precisará se preocupar com os tipos, exceto nos casos óbvios, mas eles ainda serão verificados estaticamente para você e você poderá evitar algumas repetições. Ondeauto
não for possível, você pode usardecltype
para expressar tipos semanticamente como contratos com base em expressões. Seu código será diferente, mas será uma mudança positiva.fonte
auto&&
em situações complexas edmundv.home.xs4all.nl/blog/2014/01/28/…const auto&
ou aconst auto
menos que eu queira mudar ou mudar explicitamente.auto str = std::string();
vez destd::string str;
?Fácil. Use-o quando não se importar com o tipo. Por exemplo
Tudo o que me importa aqui é o que
i
está no recipiente.É um pouco como typedefs.
Aqui, eu não me importo se
h
ew
são carros alegóricos ou duplos, apenas que eles sejam do tipo adequado para expressar alturas e pesos .Ou considere
Aqui tudo o que me interessa é que é um iterador adequado, suportando
operator++()
, é como digitar pato a esse respeito.Além disso, o tipo de lambdas não pode ser escrito, assim
auto f = []...
como o bom estilo. A alternativa é converter para,std::function
mas isso vem com sobrecarga.Eu realmente não posso conceber um "abuso" de
auto
. O mais próximo que posso imaginar é privar-se de uma conversão explícita para algum tipo significativo - mas você não usariaauto
para isso, construiria um objeto do tipo desejado.Se você pode remover alguma redundância no seu código sem introduzir efeitos colaterais, deve ser bom fazê-lo.
Contra-exemplos (emprestados das respostas de outra pessoa):
Aqui nos importamos com o tipo, então devemos escrever
Someclass i;
efor(unsigned x = y;...
fonte
auto
.Vá em frente. Use em
auto
qualquer lugar que facilite a escrita de código.Todo novo recurso em qualquer idioma será usado em excesso por pelo menos alguns tipos de programadores. Somente através do uso moderado de alguns programadores experientes (e não noobs) é que os demais programadores experientes aprendem os limites do uso adequado. O uso excessivo extremo geralmente é ruim, mas pode ser bom porque esse uso excessivo pode levar a melhorias no recurso ou a um recurso melhor para substituí-lo.
Mas se eu estivesse trabalhando em código com mais de algumas linhas como
onde o tipo é indicado zero vezes, convém alterar essas linhas para incluir tipos. O primeiro exemplo é ótimo, já que o tipo é declarado uma vez e
auto
evita a necessidade de escrever tipos de modelo confusos duas vezes. Viva o C ++++. Mas mostrar explicitamente o tipo zero vezes, se não for facilmente visível em uma linha próxima, me deixa nervoso, pelo menos em C ++ e seus sucessores imediatos. Para outras linguagens projetadas para trabalhar em um nível mais alto com mais abstração, polimorfismo e genicidade, tudo bem.fonte
No C ++ e Beyond 2012, no painel Ask Us Anything , houve uma troca fantástica entre Andrei Alexandrescu, Scott Meyers e Herb Sutter falando sobre quando usar e não usar
auto
. Pule para o minuto 25:03 para uma discussão de 4 minutos. Todos os três alto-falantes dão excelentes pontos que devem ser lembrados para quando não usarauto
.Encorajo muito as pessoas a chegarem a sua própria conclusão, mas minha opção foi usar em
auto
qualquer lugar, a menos que :O uso liberal de
explicit
ajuda a reduzir a preocupação com o último, o que ajuda a minimizar a quantidade de tempo que o primeiro é um problema.Reformulando o que Herb disse, "se você não estiver usando X, Y e Z, use
auto
. Aprenda o que X, Y e Z são e vá adiante e use emauto
qualquer outro lugar".fonte
Sim, pode ser usado em excesso em detrimento da legibilidade. Sugiro usá-lo nos contextos em que tipos exatos são longos, indizíveis ou pouco importantes para facilitar a leitura, e as variáveis têm vida curta. Por exemplo, o tipo de iterador geralmente é longo e não é importante; portanto
auto
, funcionaria:auto
aqui não prejudica a legibilidade.Outro exemplo é o tipo de regra do analisador, que pode ser longo e complicado. Comparar:
com
Por outro lado, quando o tipo é conhecido e é simples, é muito melhor se declarar explicitamente:
ao invés de
fonte
begin()
eend()
, ou o tamanho da sua etapa for diferente de um, ou você estiver modificando o contêiner enquanto faz um loop, a declaração de base para o intervalo não o ajudará.r_and_t<r_and_t<r_char_t<char>&, r_char_t<char>&>, r_char_t<char>&>
faz?space
é o tipo e procurar por isso. De qualquer forma, essas são as informações mais úteis ... afinal, o problema não é "que tipo é essa nova variável", mas "o quespace & space & space
significa?" O tipo real da expressão é apenas ruído.auto
pode ser muito perigoso em combinação com modelos de expressão que são muito usados por bibliotecas de álgebra linear, como Eigen ou OpenCV.Erros causados por esse tipo de erro são um grande problema para depuração. Um remédio possível é converter explicitamente o resultado para o tipo esperado, se você estiver empenhado em usar auto para o estilo de declaração da esquerda para a direita.
fonte
A*B
expressão seja copiada ou não em umaauto
variável ou em outra coisa, o comportamento que você descreve ainda está presente.auto
.diag(A * B)
, não precisa desperdiçar ciclos computando os elementos fora da diagonal.Uso
auto
sem restrição e não enfrentei nenhum problema. Às vezes, até acabo usando-o para tipos simples comoint
. Isso faz do c ++ uma linguagem de nível superior para mim e permite declarar variáveis em c ++ como em python. Depois de escrever o código python, às vezes até escrevoao invés de
Este é um caso em que eu diria que é um abuso da
auto
palavra - chave.Frequentemente, eu não me importo com o tipo exato de objeto, estou mais interessado em sua funcionalidade e, como os nomes das funções geralmente dizem algo sobre os objetos que eles retornam,
auto
não dói: por exemploauto s = mycollection.size()
, posso supor ques
será um tipo de número inteiro e, no raro caso em que me importo com o tipo exato, vamos verificar o protótipo da função (quero dizer, prefiro verificar quando preciso das informações, em vez de a priori quando o código é escrito, apenas caso isso seja útil algum dia, como emint_type s = mycollection.size()
).Sobre este exemplo da resposta aceita:
No meu código, ainda uso
auto
neste caso e, se querox
cancelar a assinatura, uso uma função de utilitário, chamada saymake_unsigned
, que expressa claramente minhas preocupações:isenção de responsabilidade: acabei de descrever meu uso, não sou competente para dar conselhos!
fonte
auto i = MyClass()
.as_unsigned
é recomendado lá, ou mesmoauto w = widget{};
.Um dos principais problemas do programa C ++ é que ele permite que você use a variável não inicializada . Isso nos leva a um comportamento desagradável e não determinístico do programa. Deve-se notar que o compilador moderno agora lança mensagens de aviso / mensagem apropriadas se o programa cansar de usá-lo.
Apenas para ilustrar isso, considere abaixo o programa c ++:
Se eu compilar este programa usando o compilador moderno (GCC), ele fornecerá o aviso. Esse aviso pode não ser muito óbvio se estivermos trabalhando com o código de produção complexo real.
==================================================== =============================== Agora, se mudarmos o nosso programa que usa auto , em seguida, compilar obtemos a seguinte:
Com auto, não é possível usar a variável não inicializada. Essa é a grande vantagem que podemos obter (de graça), se começarmos a usar o auto .
Este conceito e outro ótimo conceito moderno de C ++ são explicados pelo especialista em C ++ Herb Shutter em sua palestra em CppCon14 :
De volta ao básico! Fundamentos do estilo C ++ moderno
fonte
auto
.auto
- mas não precisa disso para evitar esse problema.Um perigo que notei é em termos de referências. por exemplo
O problema é another_ref não é realmente uma referência neste caso, é MyBigObject em vez de MyBigObject &. Você acaba copiando um objeto grande sem perceber.
Se você está obtendo uma referência diretamente de um método, pode não pensar no que realmente é.
você precisaria de "auto" ou "const auto"
fonte
Use
auto
onde faz sentido que um tipo seja inferido. Se você tem algo que você sabe que é um número inteiro, ou você sabe que é uma string, use int / std :: string, etc. ou ofusca código.Essa é a minha opinião de qualquer maneira.
fonte
auto
A palavra-chave pode ser usada apenas para a variável local, não para argumentos ou membros de classe / estrutura. Portanto, é seguro e viável usá-los em qualquer lugar que você quiser. Eu os uso muito. O tipo é deduzido no momento da compilação, o depurador mostra o tipo durante a depuração, ossizeof
relatórios corretamente, odecltype
tipo correto seria - não há nenhum dano. Eu não contoauto
como muito usado, nunca!fonte
TL; DR: Veja a regra geral na parte inferior.
A resposta aceita sugere a seguinte regra prática:
Mas eu diria que é muito restritivo. Às vezes, não me importo com os tipos, pois a declaração é informativa o suficiente sem que eu me preocupe em dedicar um tempo para descobrir o tipo. O que quero dizer com isso? Considere o exemplo que apareceu em algumas das respostas:
O que torna isso um exemplo de uso indevido
auto
? É minha ignorância dof()
tipo de retorno? Bem, pode realmente ajudar se eu soubesse, mas - essa não é minha principal preocupação. O que é muito mais problemático é issox
ef()
é bastante sem sentido. Se tivéssemos:em vez disso, normalmente não me importo se o tipo de retorno da função é óbvio ou não. Lendo a declaração, eu sei o que estou fazendo e sei o suficiente sobre qual é a semântica do valor de retorno para não sentir que também preciso conhecer seu tipo.
Portanto, minha resposta é: Use
auto
sempre que o compilador permitir, a menos que:E também:
auto
pelo tipo concreto.fonte
Uma das minhas experiências amargas
auto
é usá-lo com expressões lambda :Na verdade, aqui
i
é resolvido para funcionar como ponteiro deint(*)()
. Isso é simplescout
, mas imagine que tipo de erros de compilação / tempo de execução incorretos podem causar quando usadostemplate
.Você deve evitar
auto
essas expressões e colocar umreturn
tipo adequado (ou controladodecltype()
)O uso correto para o exemplo acima seria,
fonte
()
no final. Os lambdas existem para atuar como funções e é daí que a conversão do ponteiro de função vem. Se você quiser chamá-lo imediatamente, por que usar um lambda?auto i = 0;
funciona muito bem.auto x = []() { /* .... whatever goes in here ... */ }()
é melhor queauto x = /* .... whatever goes in here ... */;
, ou seja, a mesma coisa, sem o lambda? Acho isso inútil, pelo mesmo motivo que nãoauto x = 42 + y - 42
faz sentido.