Palavra-chave auto (dedução de tipo)
Deduz o tipo de uma variável declarada da expressão de inicialização.
auto declarator initializer;
Comentários
A palavra-chave auto direciona o compilador para usar a expressão de inicialização de uma variável declarada para deduzir o tipo.
Recomendamos que você use a palavra-chave auto para a maioria das situações, a menos que você realmente deseje uma conversão, pois ela fornece estes benefícios:
Vigor: se o tipo da expressão for modificado, e isso inclui a alteração de um tipo de retorno da função, ele apenas funciona.
Desempenho: você tem a garantia de que não haverá conversão.
Usabilidade: você não precisa se preocupar com dificuldades e erros de ortografia do nome do tipo.
Eficiência: a codificação pode ser mais eficiente.
Casos de conversão nos quais você pode não querer usar auto:
Quando você desejar um tipo específico e nada mais serve.
O auxiliar do modelo de expressão do tipo, como por exemplo, (valarray+valarray) e listas do inicializador, ainda que raramente você escolheria a gravação de auto x = { 1 }; e esperaria realmente obter int.
Para usar a palavra-chave auto, use-a em vez de um tipo para declarar uma variável e especifique uma expressão de inicialização. Além disso, você pode alterar a palavra-chave auto usando especificadores e declaradores como const, volatile, ponteiro (*), referência (&) e a referência de rvalue (&&). O compilador avalia a expressão e de inicialização e usa essas informações para deduzir o tipo da variável.
A expressão de inicialização pode ser uma atribuição (sintaxe de sinal de igualdade), uma inicialização direta (sintaxe de estilo de função), uma expressão do operador new ou a expressão de inicialização pode ser o parâmetro for-range-declaration em uma instrução Instrução for com base em intervalo (C++). Para obter mais informações, consulte Inicializadores e exemplos de código mais adiante neste documento.
A palavra-chave auto é um espaço reservado para um tipo, mas não é um tipo ela mesma. Portanto, a palavra-chave auto não pode ser usada nas conversões ou operadores como sizeof e typeID.
Utilidade
A palavra-chave auto é uma maneira simples de declarar uma variável que tenha um tipo complicado. Por exemplo, você pode usar auto para declarar uma variável onde a expressão de inicialização envolve modelos, ponteiros para as funções ou ponteiros para os membros.
Você também pode usar auto para declarar e inicializar uma variável em uma expressão lambda. Você não pode declarar o tipo da variável você mesmo pois o tipo de uma expressão lambda é conhecido apenas pelo compilador. Para obter mais informações, consulte Exemplos de expressões lambda.
Rastreamento de tipos de retorno
Você pode usar auto junto ao especificador de tipo decltype para ajudar a escrever bibliotecas do modelo. Use auto e decltype para declarar uma função de modelo cujo tipo de retorno dependa dos tipos dos argumentos de modelo. Ou, pode usar auto e decltype para declarar uma função do modelo que envolve uma chamada para outra função e então retorna o que for o tipo de retorno dessa outra função. Para obter mais informações, consulte Especificador de tipo decltype.
Referências e qualificadores CV
Observe que o uso de auto solta referências, qualificadores de constante e qualificadores voláteis. Considere o exemplo a seguir:
// cl.exe /analyze /EHsc /W4
#include <iostream>
using namespace std;
int main( )
{
int count = 10;
int& countRef = count;
auto myAuto = countRef;
countRef = 11;
cout << count << " ";
myAuto = 12;
cout << count << endl;
}
Você pode acreditar que myAuto é uma referência int, mas não é. Ele simplesmente é um int, portanto o resultado é 11 11 e não 11 12, como seria o caso se a referência não tivesse sido solta por auto.
Limitações e mensagens de erro
A tabela a seguir lista as limitações no uso da palavra-chave auto e a mensagem de erro de diagnóstico correspondente, emitida pelo compilador.
Número do erro |
Descrição |
---|---|
A palavra-chave auto não pode ser combinada com qualquer outro especificador de tipo. |
|
Um símbolo que é declarado com a palavra-chave auto deve ter um inicializador. |
|
Você usou incorretamente a palavra-chave auto para declarar um tipo. Por exemplo, você declarou um tipo de retorno do método ou matriz. |
|
Um argumento de modelo ou parâmetro não pode ser declarado com a palavra-chave auto. |
|
Um símbolo que é declarado com a palavra-chave auto em uma expressão new deve ter um inicializador. Para obter mais informações, consulte operador new (<new>). |
|
Um parâmetro de modelo ou método não pode ser declarado com a palavra-chave auto. |
|
Um símbolo não pode ser usado antes de ser inicializado. Na prática, isso significa que uma variável não pode ser usada para se inicializar. |
|
Você não converter para um tipo que é declarado com a palavra-chave auto. |
|
Todos os símbolos em uma lista de declaradores que são declarados com a palavra-chave auto devem ser resolvidos para o mesmo tipo. Para obter mais informações, consulte Declarações. |
|
Os operadores sizeof e typeID não podem ser aplicados a um símbolo que é declarado com a palavra-chave auto. |
Exemplos
Estes fragmentos de código ilustram alguns modos de uso da palavra-chave auto.
As declarações a seguir são equivalentes. Na primeira instrução, a variável j é declarada como tipo int. Na segunda instrução, a variável k é deduzida como sendo do tipo int pois a expressão de inicialização (0) é um inteiro.
int j = 0; // Variable j is explicitly type int.
auto k = 0; // Variable k is implicitly type int because 0 is an integer.
As seguintes declarações são equivalentes, mas a segunda declaração é mais simples do que a primeira. Um dos motivos mais convincentes para o uso da palavra-chave auto é a simplicidade.
map<int,list<string>>::iterator i = m.begin();
auto i = m.begin();
O fragmento de código a seguir declara o tipo de variável iter e elem quando os loops de for e de for do intervalo são iniciados.
// cl /EHsc /nologo /W4
#include <deque>
using namespace std;
int main()
{
deque<double> dqDoubleData(10, 0.1);
for (auto iter = dqDoubleData.begin(); iter != dqDoubleData.end(); ++iter)
{ /* ... */ }
// prefer range-for loops with the following information in mind
// (this applies to any range-for with auto, not just deque)
for (auto elem : dqDoubleData) // COPIES elements, not much better than the previous examples
{ /* ... */ }
for (auto& elem : dqDoubleData) // observes and/or modifies elements IN-PLACE
{ /* ... */ }
for (const auto& elem : dqDoubleData) // observes elements IN-PLACE
{ /* ... */ }
}
O fragmento de código a seguir usa a declaração do operador new e um ponteiro para declarar ponteiros.
double x = 12.34;
auto *y = new auto(x), **z = new auto(&x);
O próximo fragmento de código declara vários símbolos em cada instrução de declaração. Observe que todos os símbolos em cada instrução são resolvidos para o mesmo tipo.
auto x = 1, *y = &x, **z = &y; // Resolves to int.
auto a(2.01), *b (&a); // Resolves to double.
auto c = 'a', *d(&c); // Resolves to char.
auto m = 1, &n = m; // Resolves to int.
Esse fragmento de código usa o operador condicional (?:) para declarar a variável x como um inteiro com o valor de 200:
int v1 = 100, v2 = 200;
auto x = v1 > v2 ? v1 : v2;
O fragmento de código a seguir inicializa a variável x para o tipo int, variável y para uma referência para um tipo const int, e variável fp para um ponteiro para uma função que retorna o tipo int.
int f(int x) { return x; }
int main()
{
auto x = f(0);
const auto & y = f(1);
int (*p)(int x);
p = f;
auto fp = p;
//...
}
Consulte também
Referência
Especificadores de classe de armazenamento