Palavra-chave automática C ++. Por que isso é mágico?

144

De todo o material que aprendi em C ++, autosempre foi um especificador de duração de armazenamento estranho que não tinha nenhum objetivo. Mas, recentemente, encontrei um código que o usava como um nome de tipo por si só. Por curiosidade, eu tentei, e assume o tipo do que quer que eu atribua a ele!

De repente, os iteradores STL e, bem, qualquer coisa que use modelos é 10 vezes mais fácil de escrever. Parece que estou usando uma linguagem 'divertida' como Python.

Onde essa palavra-chave esteve durante toda a minha vida? Você traçará meus sonhos dizendo que é exclusivo para o visual studio ou não é portátil?

Anne Quinn
fonte
18
não é. Magia. É novo ( oh não, que trocadilho ruim ). Agora assíncrona é o futuro ( suspiro )
sehe
2
Aqui é a referência sobre palavras-chave auto en.cppreference.com/w/cpp/language/auto
andyqee

Respostas:

149

auto era uma palavra-chave que o C ++ "herdou" de C que estava lá há quase uma eternidade, mas praticamente nunca foi usada porque havia apenas duas condições possíveis: ela não era permitida ou era assumida por padrão.

O uso autopara significar um tipo deduzido era novo no C ++ 11.

Ao mesmo tempo, auto x = initializerdeduz o tipo de xdo initializermesmo modo que a dedução de tipo de modelo funciona para modelos de função. Considere um modelo de função como este:

template<class T>
int whatever(T t) { 
    // point A
};

No ponto A, um tipo foi atribuído com Tbase no valor passado para o parâmetro whatever. Quando você faz isso auto x = initializer;, a mesma dedução de tipo é usada para determinar o tipo xdo tipo initializerusado para inicializá-lo.

Isso significa que a maioria das mecânicas de dedução de tipo que um compilador precisa implementar autojá estava presente e usada para modelos em qualquer compilador que até tentou implementar o C ++ 98/03. Como tal, adicionar suporte a autoaparentemente foi bastante fácil para essencialmente todas as equipes de compiladores - foi adicionado rapidamente, e parece haver poucos bugs relacionados a ele.

Quando essa resposta foi originalmente escrita (em 2011, antes de a tinta secar no padrão C ++ 11) autojá era bastante portátil. Atualmente, é totalmente portátil entre todos os compiladores convencionais. As únicas razões óbvias para evitá-lo seriam se você precisar escrever um código compatível com um compilador C ou se tiver uma necessidade específica de direcionar algum compilador de nicho que você sabe que não o suporta (por exemplo, algumas pessoas ainda escrevem código para MS-DOS usando compiladores da Borland, Watcom, etc., que não viram atualizações significativas em décadas). Se você estiver usando uma versão razoavelmente atual de qualquer um dos compiladores convencionais, não há motivo para evitá-la.

Jerry Coffin
fonte
23

É apenas pegar uma palavra-chave geralmente inútil e fornecer uma funcionalidade nova e melhor. É padrão no C ++ 11, e a maioria dos compiladores C ++, mesmo com algum suporte ao C ++ 11, o suporta.

Nicol Bolas
fonte
Oh! Ah, nunca pensei que a linguagem C ++ fosse algo que pudesse mudar por si só. Vou ter que procurar o que mais eles adicionaram neste C ++ 11, ouvi um pouco de C ++ 0x, mas nunca me aprofundou muito nele.
Anne Quinn
7
@Clairvoire C ++ 0x era o nome provisório. Foi publicado este mês e, assim, tornou-se C ++ 11.
R. Martinho Fernandes
13

Para variáveis, especifica que o tipo da variável que está sendo declarada será deduzido automaticamente de seu inicializador. Para funções, especifica que o tipo de retorno é um tipo de retorno à direita ou será deduzido de suas instruções de retorno (desde C ++ 14).

Sintaxe

auto variable initializer   (1) (since C++11)

auto function -> return type    (2) (since C++11)

auto function   (3) (since C++14)

decltype(auto) variable initializer (4) (since C++14)

decltype(auto) function (5) (since C++14)

auto :: (6) (concepts TS)

cv(optional) auto ref(optional) parameter   (7) (since C++14)

Explicação

1) Ao declarar variáveis ​​no escopo do bloco, no escopo do namespace, nas instruções de inicialização dos loops for, etc., a palavra-chave auto pode ser usada como especificador de tipo. Depois que o tipo do inicializador é determinado, o compilador determina o tipo que substituirá a palavra-chave automaticamente usando as regras para dedução de argumento de modelo de uma chamada de função (consulte dedução de argumento de modelo # Outros contextos para obter detalhes). A palavra-chave auto pode ser acompanhada de modificadores, como const ou &, que participarão da dedução do tipo. Por exemplo, dado const auto& i = expr;, o tipo de i é exatamente o tipo do argumento u em um modelo imagináriotemplate<class U> void f(const U& u) se a função chamarf(expr)foi compilado. Portanto, auto && pode ser deduzido como uma referência lvalue ou rvalue reference de acordo com o inicializador, que é usado no loop for baseado em intervalo. Se auto for usado para declarar várias variáveis, os tipos deduzidos deverão corresponder. Por exemplo, a declaração auto i = 0, d = 0.0;está mal formada, enquanto a declaração auto i = 0, *p = &i;está bem formada e o auto é deduzido como int.

2) Em uma declaração de função que usa a sintaxe do tipo de retorno à direita, a palavra-chave auto não executa a detecção automática de tipo. Ele serve apenas como parte da sintaxe.

3) Em uma declaração de função que não usa a sintaxe do tipo de retorno à direita, a palavra-chave auto indica que o tipo de retorno será deduzido do operando de sua instrução de retorno usando as regras para dedução de argumento do modelo.

4) Se o tipo declarado da variável for decltype (auto), a palavra-chave auto será substituída pela expressão (ou lista de expressões) de seu inicializador e o tipo real será deduzido usando as regras para decltype.

5) Se o tipo de retorno da função for declarado decltype (auto), a palavra-chave auto será substituída pelo operando de sua declaração de retorno e o tipo de retorno real será deduzido usando as regras para decltype.

6) Um especificador de nome aninhado do formulário auto :: é um espaço reservado que é substituído por um tipo de classe ou enumeração, seguindo as regras para dedução de espaço reservado do tipo restrito.

7) Uma declaração de parâmetro em uma expressão lambda. (desde C ++ 14) Uma declaração de parâmetro de função. (conceitos TS)

Notas Até C ++ 11, auto tinha a semântica de um especificador de duração de armazenamento. Misturar variáveis ​​e funções automáticas em uma declaração, como em, auto f() -> int, i = 0;não é permitido.

Para mais informações: http://en.cppreference.com/w/cpp/language/auto

Prathamesh Aware
fonte
11

Essa funcionalidade não esteve presente a vida toda. É suportado no Visual Studio desde a versão 2010. É um novo recurso do C ++ 11, portanto não é exclusivo do Visual Studio e é / será portátil. A maioria dos compiladores já o suporta.

R. Martinho Fernandes
fonte
3

Não vai a lugar nenhum ... é um novo recurso C ++ padrão na implementação do C ++ 11. Dito isto, embora seja uma ferramenta maravilhosa para simplificar as declarações de objetos, além de limpar a sintaxe de certos paradigmas de chamada (ou seja, loops de loops baseados em intervalo), não o use / abuse demais :-)

Jason
fonte
3

A palavra-chave auto especifica que o tipo da variável que está sendo declarada será automaticamente deduzido do inicializador. No caso de funções, se o tipo de retorno for automático, isso será avaliado pela expressão do tipo de retorno no tempo de execução.

Pode ser muito útil quando precisamos usar o iterador. Por exemplo, para o código abaixo, podemos simplesmente usar o "auto" em vez de escrever toda a sintaxe do iterador.

int main() 
{ 

// Initialize set 
set<int> s; 

s.insert(1); 
s.insert(4); 
s.insert(2); 
s.insert(5); 
s.insert(3); 

// iterator pointing to 
// position where 2 is 
auto pos = s.find(3); 

// prints the set elements 
cout << "The set elements after 3 are: "; 
for (auto it = pos; it != s.end(); it++) 
    cout << *it << " "; 

return 0; 
}

É assim que podemos usar a palavra-chave "auto"

rahul goyal
fonte
0

É Magic é sua capacidade de reduzir a necessidade de escrever código para cada tipo de variável passado para funções específicas. Considere uma função print () similar ao Python em sua base C.

#include <iostream>
#include <string>
#include <array>

using namespace std;

void print(auto arg) {
     cout<<arg<<" ";
}

int main()
{
  string f = "String";//tok assigned
  int x = 998;
  double a = 4.785;
  string b = "C++ Auto !";
//In an opt-code ASCII token stream would be iterated from tok's as:
  print(a);
  print(b);
  print(x);
  print(f);
}
rodeone2
fonte