Rodrigo Strauss :: Blog
C++11: auto
A palavra chave auto já existe no C++ desde os tempos mais primórdios. Ela sempre era (sim, era) um modificador de storage de variáveis. Você podia escolher o modificador auto para variáveis de armazenamento automático e register para armazenar a variável em um registrador. Esse modificador hoje em dia é implícito: se não especificado o armazenamento o compilador decide onde armazenar. De forma automática. O modificador register, até onde sei, é grande conhecido do pessoal de embarcados, que muitas vezes trabalham com recursos limitados e precisam gerenciá-los a ponto de dizer ao compilador onde a variável x será armazenada.
Interessante lembrar que a palavra chave register gera alguns efeitos colaterais, como a impossibilidade de pegar o endereço da variável com o operador &. E tem ainda o fato de que muitos compiladores modernos simplesmente não respeitam o register.
- //
- // Eu dizendo ao compilador que quero a variável a
- // *preferencialmente* armazenada em um registrador.
- //
- register int a = 10;
- //
- // Eu dizendo para o compilador "eis minha variável b, enfie
- // onde bem entender"
- //
- auto int b = 42;
- //
- // Quando não especifico nada, o "enfie onde quiser"
- // está subentendido
- //
- int c = 42;
Com o padrão C++11 o significado dessa palavra chave foi modificada. Agora ela é usada para tipar uma variável de acordo com a expressão a ela atribuída. Na linha "int a = "2 + 2", o compilador sabe que a expressão "2 + 2" retorna um tipo inteiro - na realidade o compilador sempre sabe o tipo de uma expressão em uma linguagem tipada - e pode muito bem acertar a declaração de acordo.
Esse recurso não é lá muito útil para expressões simples e pode até prejudicar a legibilidade do código, já que o leitor terá que efetuar de cabeça a mesma avaliação de expressão que o compilador fez. Ele realmente se torna útil para tipos e subtipos de classes templates, onde só o tamanho da declaração do tipo da variável pode tomar mais da metade da tela. Exemplo:
- //
- // Variável a será do tipo int
- //
- auto a = 10;
- //
- // Variável f será do tipo double, devido à regra de promoção de tipos
- //
- auto f = 10 * 2.0;
- std::map<std::string, std::string> um_mapa;
- //
- // Variável i será do tipo informado
- //
- std::map<std::string, std::string>::iterator i = um_mapa.begin();
- //
- // Variável biggie_smalls terá o mesmo tipo da variável i,
- // mas economizando bastante espaço
- //
- auto biggie_smalls = um_mapa.begin();
- //
- // Só pra mostrar que essa coisa toda funciona
- //
- assert(i == biggie_smalls);
- i = biggie_smalls;
- //
- // ISSO NÃO FUNCIONA. É preciso haver uma atribuição para
- // que o compilador saiba qual o tipo
- //
- auto x; // <- error 12345: you really don't know how to use auto, do you?
Para quem programa em coisas tipo Haskell isso pode parecer óbvio. Mas já vi trocentas pessoas achando que isso é uma tentativa de transformar C++ em uma linguagem dinâmica. Então, só pra garantir:
A "nova" palavra chave auto NÃO TORNA O C++ UMA LINGUAGEM DINÂMICA. O tipo ainda é estático, você só não precisa informá-lo quando o compilador consegue deduzir isso sozinho.
Ah, isso é equivalente ao var do C# e igual ao funcionamento de declaração de variáveis da linguagem Go. E *não* é igual à declaração de variável em Python, Ruby ou Perl.
Mais um exemplo, e caso específico onde o auto é mais usado:
- using std::string;
- using std::map;
- using std::vector;
- map<string, vector<string>> connections;
- //
- // Como é hoje
- //
- for(map<string, vector<string>>::iterator i = connections.begin() ; i != connections.end() ; ++i)
- {
- }
- //
- // Muito mais fácil de ler.
- //
- for(auto i = connections.begin() ; i != connections.end() ; ++i)
- {
- }
Em 28/11/2011 14:39, por Rodrigo Strauss





Pessoalmente, acho que o novo "auto" dificulta a compreensão imediata do código. Provavelmente usarei pouco - se é que usarei.