Existe uma desvantagem em declarar variáveis ​​com auto em C ++?


143

Parece que autofoi um recurso bastante significativo a ser adicionado no C ++ 11 que parece seguir muitas das linguagens mais recentes. Como em uma linguagem como Python, não vi nenhuma declaração explícita de variável (não tenho certeza se é possível usar os padrões Python).

Existe uma desvantagem em usar autopara declarar variáveis ​​em vez de declará-las explicitamente?


1
Consulte também: stackoverflow.com/questions/6434971/… , stackoverflow.com/questions/15254461/… , stackoverflow.com/questions/6900459/… , stackoverflow.com/questions/8430053/is-c11-auto-type-dangerous e talvez outros. Não tenho certeza se essas são duplicatas exatas, mas são definitivamente candidatas.
Cody Gray

3
A única desvantagem que encontrei foi quando tive que portar uma base de código para uma plataforma (console) cujo compilador não suportava (e não tinha intenção de dar suporte) aos recursos do C ++ 11!
Sam

7
Apenas para completar GotW # 94 "Quase sempre automático": herbsutter.com/2013/08/12/…
Richard Critten 13/01/16

1
Eu estava ouvindo o cppcast e havia menção de inicializadores de confronto automático a preto e branco e lista. Vou tentar encontrar esse podcast.
Abhinav Gauniyal

2
a primeira desvantagem que eu acho que está afetando a legibilidade do código
ggrr

Respostas:


111

Você só perguntou sobre desvantagens, então estou destacando algumas delas. Quando usado bem, autotem várias vantagens também. As desvantagens resultam da facilidade de abuso e do aumento do potencial do código para se comportar de maneira não intencional.

A principal desvantagem é que, ao usar auto, você não conhece necessariamente o tipo de objeto que está sendo criado. Há também ocasiões em que o programador pode esperar que o compilador deduza um tipo, mas o compilador deduz com firmeza outro.

Dada uma declaração como

auto result = CallSomeFunction(x,y,z);

você não tem necessariamente conhecimento de que tipo resulté. Pode ser um int. Pode ser um ponteiro. Pode ser outra coisa. Todos esses suportam operações diferentes. Você também pode alterar drasticamente o código com uma pequena alteração, como

auto result = CallSomeFunction(a,y,z);

porque, dependendo das sobrecargas existentes para CallSomeFunction()o tipo de resultado, pode ser completamente diferente - e, portanto, o código subsequente pode se comportar de maneira totalmente diferente do pretendido. Você pode disparar mensagens de erro repentinamente em códigos posteriores (por exemplo, subseqüentemente tentando desreferenciar um int, tentando mudar algo que está agora const). A mudança mais sinistra é onde sua mudança passa pelo compilador, mas o código subsequente se comporta de maneiras diferentes e desconhecidas - possivelmente com erros.

Não ter conhecimento explícito do tipo de algumas variáveis, portanto, torna mais difícil justificar rigorosamente uma afirmação de que o código funciona como pretendido. Isso significa mais esforço para justificar reivindicações de "adequação à finalidade" em domínios de alta criticidade (por exemplo, crítica à segurança ou crítica à missão).

A outra desvantagem mais comum é a tentação de um programador usar autocomo um instrumento contundente para forçar a compilação do código, em vez de pensar no que o código está fazendo e trabalhar para corrigi-lo.


58
É interessante notar que, se tais exemplos são a desvantagem do uso auto, a maioria das linguagens tipadas por pato sofre essa desvantagem por design!
Leben Asa

11
Se CallSomeFunction()retornar um tipo diferente, dependendo da sequência de seus argumentos, isso é um defeito de design CallSomeFunction(), não um problema de auto. Se você não lê a documentação de uma função que está usando antes de usá-la, isso é um defeito do programador, não um problema auto. - Mas eu entendo que você está bancando o advogado do diabo aqui, é que Nir Friedman tem um caso muito melhor.
DevSolar

16
@ DevSolar: Por que T CallSomeFunction(T, int, int)haveria um defeito de design? Obviamente, "retorna um tipo diferente, dependendo da sequência de seus argumentos".
MSalters

9
"A principal desvantagem é que, ao usar auto, você não conhece necessariamente o tipo de objeto que está sendo criado." Você pode explicar por que isso é um problema autoe não um problema com temporários de subexpressão? Por que é auto result = foo();ruim, mas foo().bar()não?
Angew não está mais orgulhoso de SO

24
Parece a partir dos comentários que "desvantagem" está sendo interpretada como uma razão pela qual algo é inaceitável. Uma desvantagem de um recurso de linguagem é uma desvantagem que o desenvolvedor precisa considerar e justificar aceitar ou não - ou seja, fazer trocas de engenharia. Não estou fazendo alegações gerais sobre por que o recurso deve ou não ser usado.
Peter

76

Isso não é autoexatamente uma desvantagem de princípios, mas em termos práticos parece ser um problema para alguns. Basicamente, algumas pessoas: a) tratam autocomo salvadores de tipos e desligam o cérebro ao usá-lo; ou b) esquecem que autosempre deduz aos tipos de valor. Isso faz com que as pessoas façam coisas assim:

auto x = my_obj.method_that_returns_reference();

Opa, nós apenas copiamos profundamente algum objeto. Geralmente, é um bug ou uma falha no desempenho. Então, você pode mudar para o outro lado:

const auto& stuff = *func_that_returns_unique_ptr();

Agora você recebe uma referência pendente. Esses problemas não são causados ​​por autonada, então não os considero argumentos legítimos contra ele. Mas parece que autoessas questões são mais comuns (por experiência própria), pelas razões que listei no começo.

Penso que, com o tempo, as pessoas se ajustarão e entenderão a divisão do trabalho: autodeduz o tipo subjacente, mas você ainda deseja pensar em referência e constância. Mas está demorando um pouco.


Por que você pode copiar em profundidade um objeto caro, para começar?
Laurent LA RIZZA 14/01

3
@LaurentLARIZZA: Algumas classes têm construtores de cópia simplesmente porque às vezes são necessárias (por exemplo, instâncias de std::vector). Ser caro copiar não é propriedade de uma classe, mas de objetos individuais. Portanto, method_that_returns_referencepode se referir a um objeto de uma classe que possui um construtor de cópias, mas que objeto é muito caro para copiar (e não pode ser movido de).
Marc van Leeuwen

@MarcvanLeeuwen: Se o objeto é caro para copiar e não pode ser movido, por que ele seria armazenado em um arquivo std::vector? (Porque pode sim, ou porque você não controla a classe, mas esse não é o ponto) Se é caro copiar (e não possui nenhum recurso, porque é copiável), por que não usar COW no objeto? A localidade dos dados já foi eliminada pelo tamanho do objeto.
Laurent LA RIZZA 14/01

2
@LaurentLARIZZA Não é uma instância de algo armazenado em um vetor que seja caro, apenas um vetor regular, por exemplo, <double> é caro para copiar, é uma alocação de heap + O (N). Mover é um arenque vermelho. A primeira linha que mostrei copiará, não será movida, a menos que a referência retornada seja uma referência rvalue. A vaca não está realmente aqui nem ali. O fato é que sempre é caro copiar objetos.
Nir Friedman

4
@Yakk Não pode fazer isso com segurança, porque pode cortar. A única coisa segura que pode fazer é = deleteessa sobrecarga. Embora, geralmente, o que você diz seja uma solução. Este é um tópico que eu explorei, se você estiver interessado: nirfriedman.com/2016/01/18/… .
Nir Friedman

51

Outras respostas estão mencionando desvantagens como "você realmente não sabe qual é o tipo de variável". Eu diria que isso está amplamente relacionado à convenção de nomes desleixados no código. Se suas interfaces tiverem um nome claro, você não precisará se importar com o tipo exato. Claro, auto result = callSomeFunction(a, b);não diz muito. Mas auto valid = isValid(xmlFile, schema);diz o suficiente para você usar validsem ter que se importar com o seu tipo exato. Afinal, com apenas if (callSomeFunction(a, b)), você também não saberia o tipo. O mesmo com qualquer outro objeto temporário de subexpressão. Portanto, não considero isso uma verdadeira desvantagem auto.

Eu diria que sua principal desvantagem é que, às vezes, o tipo de retorno exato não é o que você deseja trabalhar. De fato, algumas vezes o tipo de retorno real difere do tipo de retorno "lógico" como um detalhe de implementação / otimização. Modelos de expressão são um excelente exemplo. Digamos que temos o seguinte:

SomeType operator* (const Matrix &lhs, const Vector &rhs);

Logicamente, esperamos SomeTypeser Vector, e definitivamente queremos tratá-lo como tal em nosso código. No entanto, é possível que, para fins de otimização, a biblioteca de álgebra que estamos usando implementa modelos de expressão, e o tipo de retorno real seja este:

MultExpression<Matrix, Vector> operator* (const Matrix &lhs, const Vector &rhs);

Agora, o problema é que MultExpression<Matrix, Vector>a vontade em toda a loja de probabilidade de um const Matrix&e const Vector&internamente; espera que seja convertido em a Vectorantes do final de sua expressão completa. Se temos esse código, está tudo bem:

extern Matrix a, b, c;
extern Vector v;

void compute()
{
  Vector res = a * (b * (c * v));
  // do something with res
}

No entanto, se tivéssemos usado autoaqui, poderíamos ter problemas:

void compute()
{
  auto res = a * (b * (c * v));
  // Oops! Now `res` is referring to temporaries (such as (c * v)) which no longer exist
}

3
@NirFriedman Você está certo, é forte, mas eu realmente sinto que autotem muito poucas desvantagens, então mantenho essa força. E outros exemplos de proxies etc. incluem vários "construtores de cadeias" e objetos semelhantes encontrados nas DSLs.
Angew não está mais orgulhoso de SO

2
Fui mordido por modelos de expressão e autoantes, especificamente com a biblioteca Eigen. É especialmente complicado porque o problema geralmente não aparece nas compilações de depuração.
Dan

1
O uso de autotambém pode morder ao usar a biblioteca de matriz do Armadillo , que faz uso intenso da meta-programação de modelos para fins de otimização. Felizmente, os desenvolvedores adicionaram a função .eval () que pode ser usada para evitar problemas comauto
mtall

2
"Se suas interfaces tiverem um nome claro, você não precisará se importar com o tipo exato" Seu compilador não pode verificar a correção do seu código estudando os nomes das variáveis. Este é o ponto inteiro de um sistema de tipos. Ignorar cegamente é bobagem!
Lightness Races in Orbit

1
@ Angular: Não é um problema para os temporários, porque geralmente você os usa imediatamente, o que autogeralmente não envolve algum tipo de verificação de tipo (e espirrar autoem todos os lugares retira esse tipo de segurança, assim como em qualquer outro lugar). Não é uma boa comparação.
Lightness Races in Orbit

13

Uma das desvantagens é que às vezes você não pode declarar const_iteratorcom auto. Você obterá o iterador comum (não const) neste exemplo de código extraído desta pergunta :

map<string,int> usa;
//...init usa
auto city_it = usa.find("New York");

3
Bem, você recebe um iteratorem qualquer caso, já que seu mapa não é const. se você deseja convertê-lo em a const_iterator, especifique o tipo de variável explicitamente, como de costume, ou extraia um método para que seu mapa seja const no contexto do seu find. (Eu prefiro o último SRP..)
Laurent LA RIZZA

auto city_it = static_cast<const auto&>(map).find("New York")? ou, com C ++ 17 auto city_if = std::as_const(map).find("New York"),.
Dev Null

11

Isso torna seu código um pouco mais difícil, ou tedioso, de ler. Imagine algo assim:

auto output = doSomethingWithData(variables);

Agora, para descobrir o tipo de saída, você teria que rastrear a assinatura da doSomethingWithDatafunção.


40
Nem sempre. auto it = vec.begin();é muito mais fácil de ler do que std::vector<std::wstring>::iterator it = vec.begin();por exemplo.
Jonathan Potter

4
Acordado. Depende do caso de uso. Eu poderia ter sido mais preciso sobre isso.
Skam

1
@SeeDart, sim, pessoas que usam esse tipo de automóvel estão fazendo errado.
Lciamp

6
"Rastrear a assinatura da função", se isso não for o mouse ou a tecla pressionada ("siga o símbolo" / "vá para a declaração" / como ele é chamado), você precisa configurar mais o seu editor ou mude para um IDE que pode fazer isso sem configuração ... Porém, seu ponto ainda é válido.
Hyde

6
Notei que não em um IDE, mas em pequenos orifícios de diferenças ao revisar checkins! Com o automóvel, são mais difíceis de ler por esse motivo.
JDługosz

10

Como esse desenvolvedor, eu odeio auto. Ou melhor, odeio como as pessoas fazem mau uso auto.

Sou da opinião (forte) de que autoé para ajudá-lo a escrever código genérico, não para reduzir a digitação .
C ++ é uma linguagem cujo objetivo é permitir que você escreva um código robusto, não para minimizar o tempo de desenvolvimento.
Isso é bastante óbvio em muitos recursos do C ++, mas, infelizmente, alguns dos mais novos autoreduzem a digitação das pessoas que levam a pensar que devem começar a ficar preguiçosos com a digitação.

Nos autodias anteriores , as pessoas usavam typedefs, o que foi ótimo, porque typedef permitiu ao designer da biblioteca ajudá-lo a descobrir qual deveria ser o tipo de retorno, para que a biblioteca funcionasse conforme o esperado. Quando você usa auto, tira esse controle do designer da classe e, em vez disso, pede ao compilador para descobrir qual deve ser o tipo, o que remove uma das ferramentas C ++ mais poderosas da caixa de ferramentas e corre o risco de quebrar seu código.

Geralmente, se você usar auto, deve ser porque seu código funciona para qualquer tipo razoável , não porque você é preguiçoso demais para anotar o tipo com o qual deve trabalhar. Se você usa autocomo uma ferramenta para ajudar a preguiça, o que acontece é que você acaba introduzindo erros sutis em seu programa, geralmente causados ​​por conversões implícitas que não aconteceram porque você o usou auto.

Infelizmente, esses bugs são difíceis de ilustrar em um pequeno exemplo aqui, porque sua brevidade os torna menos convincentes do que os exemplos reais que surgem em um projeto de usuário - no entanto, eles ocorrem facilmente em códigos pesados ​​de modelo que esperam que certas conversões implícitas ocorram Lugar, colocar.

Se você quiser um exemplo, há um aqui . Uma pequena observação: porém, antes de ser tentado a pular e criticar o código: lembre-se de que muitas bibliotecas conhecidas e maduras foram desenvolvidas em torno de conversões implícitas e existem porque resolvem problemas que podem ser difíceis, se não impossíveis. para resolver o contrário. Tente descobrir uma solução melhor antes de criticá-los.


3
which was great because typedef allowed the designer of the library to help you figure out what the return type should be, so that their library works as expected. When you use auto, you take away that control from the class's designer and instead ask the compiler to figure out what the type should beNão é realmente uma boa razão para IMO. IDEs atualizados, Visual Studio 2015, por exemplo, permitem verificar o tipo da variável passando o mouse sobre auto. Este é exatamente o mesmo que typedefesse.
Sombrero Chicken

@ JamesyD: Você está perdendo vários pontos cruciais: (1) Seu argumento IDE só funciona se o tipo for concreto, não modelado. Os IDEs não podem indicar o tipo correto no caso de tipos dependentes, por exemplo typename std::iterator_traits<It>::value_type. (2) O ponto principal era que o tipo inferido não precisa ser "exatamente o mesmo" que o tipo correto pretendido pelo criador anterior do código; Ao usar auto, você está diminuindo a capacidade do designer de especificar o tipo correto.
user541686

Você está basicamente falando sobre proxies, que uma das respostas já menciona. Modelos de expressão e bobagem de vetor <bool> não são códigos comuns para a maioria das pessoas. Na maioria das situações, você não deseja conversões implícitas, e a auto ajuda nisso. Herb Sutter fala sobre as vantagens do auto extensivamente em uma de suas postagens no blog, e não se trata principalmente de pressionamentos de teclas, e também não é apenas para código genérico. Além disso, no primeiro link que você forneceu, a postagem do blog é simplesmente um péssimo conselho (e é por isso que ele é criticado com veemência em sua seção de comentários).
Nir Friedman

@NirFriedman: "... vector<bool>bobagem" ... perdão? Como você acha que bitseté implementado? Ou você considera que os contêineres de bits são um absurdo?
precisa saber é o seguinte

1
@NirFriedman: Nada sobre o vetor <bool> é novidade para mim. O que estou tentando lhe dizer e que você se recusa descaradamente a entender é que, para os fins desta pergunta, o bitset não é diferente do vetor <bool> - ambos usam proxies, porque os proxies foram considerados úteis , e o fato de os proxies serem úteis é uma realidade que você precisa aceitar em vez de viver em negação. Você pode parar de transformar isso em um debate sobre se você acha que os proxies são úteis? Esse não é o assunto do debate e, também, sua opinião sobre eles é apenas sua opinião, não algum tipo de fato.
precisa saber é o seguinte

6

autonão tem desvantagens em si , e eu advogo que (manualmente) use-o em qualquer lugar do novo código. Ele permite que seu código verifique consistentemente e evite fatias silenciosas. (Se Bderiva de Ae uma função retornando Arepentinamente retorna B, então autose comporta conforme o esperado para armazenar seu valor de retorno)

Embora o código legado anterior ao C ++ 11 possa contar com conversões implícitas induzidas pelo uso de variáveis ​​de tipo explícito. Alterar uma variável de tipo explícito para autopode alterar o comportamento do código , por isso é melhor ter cuidado.


A redução de votos é justa, mas você poderia comentar sobre o porquê?
Laurent LA RIZZA 17/01

Não diminuí a votação, mas autotem desvantagens em si (ou pelo menos - muitos pensam que sim). Considere o exemplo dado na segunda pergunta neste painel de discussão com Sutter, Alexandrescu e Meyers: Se você tem auto x = foo(); if (x) { bar(); } else { baz(); }e foo()retorna bool- o que acontece se as foo()alterações retornarem uma enumeração (três opções em vez de duas)? O autocódigo continuará funcionando, mas produzirá resultados inesperados.
Einpoklum

@einpoklum: E usar algo em boolvez de automudar alguma coisa no caso de um enum sem escopo? Posso estar errado (não é possível verificar aqui), mas acho que a única diferença é que a conversão boolocorre na declaração da variável em vez de na avaliação da condição no if. Se o enumescopo for definido, a conversão para boolnão ocorrerá sem um aviso explícito.
Laurent LA RIZZA 30/03

4

A palavra-chave autosimplesmente deduz o tipo do valor retornado. Portanto, não é equivalente a um objeto Python, por exemplo

# Python
a
a = 10       # OK
a = "10"     # OK
a = ClassA() # OK

// C++
auto a;      // Unable to deduce variable a
auto a = 10; // OK
a = "10";    // Value of const char* can't be assigned to int
a = ClassA{} // Value of ClassA can't be assigned to int
a = 10.0;    // OK, implicit casting warning

Como autoé deduzido durante a compilação, ele não terá nenhuma desvantagem no tempo de execução.


1
sim, basicamente faz o que type()em python faz. Deduz o tipo, não cria uma nova variável desse tipo.
Lciamp

2
@lciamp Na verdade, isso seria decltype. autoé para atribuição de variável especificamente.
Cubic

4

O que ninguém mencionou aqui até agora, mas vale por si só uma resposta, se você me perguntasse.

Como (mesmo que todos devam estar cientes disso C != C++), o código escrito em C pode ser facilmente projetado para fornecer uma base para o código C ++ e, portanto, ser projetado sem muito esforço para ser compatível com C ++, isso pode ser um requisito para o design.

Conheço algumas regras em que algumas construções bem definidas Csão inválidas C++e vice-versa. Mas isso resultaria simplesmente em executáveis ​​quebrados e a cláusula UB conhecida se aplica, que na maioria das vezes é notada por ciclos estranhos que resultam em travamentos ou o que for (ou até pode ficar sem ser detectado, mas isso não importa aqui).

Mas autoé a primeira vez 1 isso muda!

Imagine que você usou autocomo especificador de classe de armazenamento antes e transfira o código. Nem mesmo necessariamente (dependendo da maneira como foi usado) "quebrou"; na verdade, ele pode alterar silenciosamente o comportamento do programa.

Isso é algo que se deve ter em mente.


1 Pelo menos na primeira vez que estou ciente.


1
Você receberá um erro do compilador de qualquer maneira ao tentar compilar.
Sombrero Chicken

@JameyD: O que faria isso? por que duas situações de código válidas com significado diferente podem aparecer novamente em erro?
Dhein

8
Se você está contando com "nenhum tipo implica int" em C, merece todas as coisas ruins que conseguirá com isso. E se você não está confiando nele, usar autocomo um especificador de classe de armazenamento ao lado de um tipo fornecerá um erro de compilação agradável em C ++ (que é uma Coisa Boa neste caso).
Angew não está mais orgulhoso de SO

1
@ Novamente bem, é esse o caso ao qual estou me referindo, sim. Eu não estou fazendo isso. Mas é algo que pelo menos deve ser lembrado.
Dhein

3

Uma razão pela qual consigo pensar é que você perde a oportunidade de coagir a classe retornada. Se sua função ou método retornou um longo de 64 bits e você só queria um int não assinado de 32, então você perde a oportunidade de controlá-lo.


1
Existe static_cast, e o IIRC, por exemplo, o Effective Modern C ++ de Meyers até recomenda usá-lo para especificar o tipo de variável digitada automaticamente.
Hyde

2

Como eu descrevi nesta resposta, auto às vezes pode resultar em situações estranhas que você não pretendia. Você tem que dizer explicitamente auto&para ter um tipo de referência, enquanto apenas autopode criar um tipo de ponteiro. Isso pode resultar em confusão, omitindo todo o especificador, resultando em uma cópia da referência em vez de uma referência real.


2
Isso não é divertido. É o que autoacontece, nunca inferindo uma referência nem um consttipo. Para uma autoreferência, é melhor você usar auto&&. (uma referência universal) Se o tipo não for barato para copiar ou possuir um recurso, o tipo não deverá ser copiável, para começar.
Laurent LA RIZZA 14/01

1

Outro exemplo irritante:

for (auto i = 0; i < s.size(); ++i)

gera um aviso ( comparison between signed and unsigned integer expressions [-Wsign-compare]), porque ié um int assinado. Para evitar isso, você precisa escrever, por exemplo,

for (auto i = 0U; i < s.size(); ++i)

ou talvez melhor:

for (auto i = 0ULL; i < s.size(); ++i)

1
Sim, acho este irritante também. Mas o buraco na linguagem está em outro lugar. Para que esse código seja verdadeiramente portátil, assumindo sizeretornos size_t, você teria que ter um size_ttipo literal 0z. Mas você pode declarar uma UDL para fazer isso. ( size_t operator""_z(...))
Laurent LA RIZZA 24/01

1
Objeções puramente teóricas: unsignedé provável que não seja grande o suficiente para conter todos os valores das std::size_tarquiteturas convencionais, portanto, no improvável evento de alguém ter um contêiner com um número absurdamente gigantesco de elementos, o uso unsignedpoderia causar um loop infinito no intervalo inferior de índices. Embora seja improvável que seja um problema, std::size_tdeve ser usado para obter um código limpo que sinalize corretamente a intenção. Não tenho certeza se unsigned long longé estritamente garantido o suficiente, embora, na prática, presumivelmente deva ser o mesmo.
Underscore_d

@underscore_d: sim, ponto justo - unsigned long longé garantido que seja pelo menos 64 bits, mas em teoria size_tpoderia ser maior que isso, suponho. Claro, se você tem> 2 ^ 64 elementos em seu recipiente, em seguida, você pode ter problemas maiores para se preocupar ... ;-)
Paul R

1

Eu acho que autoé bom quando usado em um contexto localizado, onde o leitor facilmente e obviamente pode deduzir seu tipo, ou bem documentado com um comentário de seu tipo ou um nome que infere o tipo real. Quem não entende como isso funciona pode levá-lo de maneira errada, como usá-lo em vez de templateou similar. Aqui estão alguns casos de uso bons e ruins na minha opinião.

void test (const int & a)
{
    // b is not const
    // b is not a reference

    auto b = a;

    // b type is decided by the compiler based on value of a
    // a is int
}

Bons usos

Iteradores

std::vector<boost::tuple<ClassWithLongName1,std::vector<ClassWithLongName2>,int> v();

..

std::vector<boost::tuple<ClassWithLongName1,std::vector<ClassWithLongName2>,int>::iterator it = v.begin();

// VS

auto vi = v.begin();

Ponteiros de Função

int test (ClassWithLongName1 a, ClassWithLongName2 b, int c)
{
    ..
}

..

int (*fp)(ClassWithLongName1, ClassWithLongName2, int) = test;

// VS

auto *f = test;

Maus usos

Fluxo de dados

auto input = "";

..

auto output = test(input);

Função Assinatura

auto test (auto a, auto b, auto c)
{
    ..
}

Casos triviais

for(auto i = 0; i < 100; i++)
{
    ..
}

Quando você quer um int, você deve digitar mais um caractere se quiser auto. Isso é inaceitável
Rerito

@Rerito sim, é inttão fácil de ver aqui e a digitação inté mais curta. É por isso que é um caso trivial.
precisa saber é o seguinte

0

Estou surpreso que ninguém tenha mencionado isso, mas suponha que você esteja calculando o fatorial de algo:

#include <iostream>
using namespace std;

int main() {
    auto n = 40;
    auto factorial = 1;

    for(int i = 1; i <=n; ++i)
    {
        factorial *= i;
    }

    cout << "Factorial of " << n << " = " << factorial <<endl;   
    cout << "Size of factorial: " << sizeof(factorial) << endl; 
    return 0;
}

Este código produzirá o seguinte:

Factorial of 40 = 0
Size of factorial: 4

Esse definitivamente não foi o resultado esperado. Isso aconteceu porque autodeduziu o tipo da variável fatorial como intporque foi atribuída 1.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.