Menu

auto in C++: la deduzione del tipo spiegata con esempi

Come la parola chiave auto permette al compilatore di dedurre per te il tipo di una variabile: cosa elimina, dove dà il meglio e le insidie che colpiscono i principianti.

Questa pagina include editor eseguibili: modifica, esegui e vedi subito l'output.

Lascia scegliere il tipo al compilatore

Nella pagina precedente hai visto che ogni variabile C++ ha un tipo fisso: int, double, std::string e così via. Scrivere il tipo a mano va bene per int count = 0;, ma diventa rumoroso quando i tipi si allungano. La parola chiave auto (da C++11 in poi) permette al compilatore di dedurre il tipo dal valore che assegni, così scrivi il valore una volta e lasci che il compilatore completi il resto.

L'idea chiave: auto non è tipizzazione dinamica. Ogni variabile ha comunque un solo tipo concreto, fissato in fase di compilazione. auto ti risparmia solo di doverlo scrivere.

Perché auto vale la pena

Per tipi brevi e ovvi, auto count = 0; e int count = 0; sono ugualmente leggibili. Dove auto ripaga davvero è con i nomi di tipo lunghi e ripetitivi, quelli che ottieni dai contenitori e dagli iteratori della libreria standard.

Confronta la versione prolissa con quella con auto:

// Senza auto: in pratica il tipo si scrive due volte
std::vector<std::pair<std::string, int>>::iterator it = scores.begin();

// Con auto: il compilatore conosce già il tipo
auto it = scores.begin();

Entrambe dichiarano esattamente lo stesso tipo di iteratore. La seconda è più facile da leggere e non smetterà di essere corretta se in seguito cambi scores con un contenitore diverso.

Eccola in un programma completo:

auto nei cicli for basati su range

Il posto in cui incontrerai auto più spesso è il ciclo for basato su range. Non vorrai quasi mai scrivere a mano il tipo degli elementi, e il modo in cui scrivi auto decide se ottieni una copia o un riferimento.

Tre varianti che vedrai, e cosa significa ciascuna:

  • for (auto x : v): x è una copia di ogni elemento. Economica per int, uno spreco per oggetti grandi.
  • for (auto& x : v): x è un riferimento; puoi modificare gli elementi sul posto.
  • for (const auto& x : v): x è un riferimento di sola lettura. Usalo quando devi solo leggere.

Il prossimo programma modifica il contenitore tramite auto&:

Attenzione: se in quel ciclo scrivi for (auto n : nums) (senza &), n *= 10 cambierebbe in silenzio solo la copia, lasciando nums intatto. Il compilatore non ti avvisa: il ciclo semplicemente non fa nulla di utile.

Cosa elimina auto

Un auto semplice deduce il tipo nello stesso modo di un parametro di funzione passato per valore: elimina il const di primo livello, i riferimenti e volatile. Questo significa che auto ti dà sempre una copia nuova e modificabile, a meno che tu non chieda altrimenti.

Se vuoi mantenere const o evitare la copia, aggiungi tu i qualificatori. Lo schema è decorare auto come decoreresti qualsiasi altro tipo:

Quindi auto deduce il tipo di base; &, const e * sono manopole che aggiungi sopra. auto è il tipo, const auto& è un riferimento di sola lettura a quel tipo.

Errori comuni e insidie

auto ti risparmia fatica nello scrivere, ma non ti esonera dal capire i tipi. Alcune trappole colpiscono i principianti:

Devi inizializzare. Da una dichiarazione vuota auto non ha nulla da dedurre, quindi questo è un errore di compilazione vero e proprio:

auto x;        // error: declaration of 'auto x' has no initializer
auto y = 0;    // corretto

I letterali interi sono int, non double. auto half = 1 / 2; deduce int e memorizza 0, perché 1 / 2 è una divisione intera prima ancora che auto la veda. Il tipo segue il valore:

auto elimina il riferimento: attenzione alle copie a sorpresa. Se una funzione restituisce un riferimento e lo prendi con un semplice auto, ottieni una copia, e in un ciclo critico a volte questo è un vero problema di prestazioni (una copia profonda di un oggetto grande a ogni iterazione). Usa const auto& quando intendi "guarda, non prendere".

Non nascondere il tipo quando conta. auto result = compute(); va bene quando il tipo restituito da compute è ovvio dal contesto, ma se chi legge deve andare a cercare cosa sia davvero result, scrivere il tipo può essere la scelta più gentile. auto serve a ridurre il rumore, non a nascondere le intenzioni.

Prossimo: Costanti e const

Hai visto che auto elimina di proposito const a meno che tu non chieda di mantenerlo, il che solleva una domanda ovvia: cosa garantisce davvero const, e quando dovresti marcare un valore come immutabile? La prossima pagina approfondisce const, le espressioni costanti e perché "rendilo const di default" è una delle abitudini più utili in C++.

Domande frequenti

A cosa serve la parola chiave auto in C++?

auto dice al compilatore di dedurre il tipo della variabile dal suo inizializzatore. auto x = 5; rende x un int; auto y = 3.14; rende y un double. Il tipo viene fissato in fase di compilazione: auto non è tipizzazione dinamica, è una scorciatoia per non scrivere il tipo a mano.

auto mantiene const e i riferimenti in C++?

No. Un auto semplice elimina il const di primo livello, i riferimenti e volatile. Se l'origine è const int& r, allora auto x = r; produce una semplice copia int. Per mantenerli devi scriverli esplicitamente: usa const auto& per legare un riferimento di sola lettura senza copiare.

Si può dichiarare una variabile con auto senza inizializzarla?

No. auto x; è un errore di compilazione, perché non c'è alcun inizializzatore da cui il compilatore possa dedurre un tipo. Ogni variabile auto deve ricevere un valore nel punto in cui viene dichiarata.

Illustrazione dei linguaggi di programmazione di Coddy

Impara a programmare con Coddy

INIZIA