Dovrei usare la nuova funzionalità 'auto' di C ++ 11, specialmente nei loop?

21

Quali sono i pro / contro nell'usare la parola chiave auto , specialmente nei cicli for?

for(std::vector<T>::iterator it = x.begin(); it != x.end(); it++ )
{
   it->something();
}

for(std::map<T>::iterator it = x.begin(); it != x.end(); it++ )
{
   it->second->something();
}

for(auto it = x.begin(); it != x.end(); it++ )
{
   it->??
}

Sembra che se non sai se hai un iteratore per una mappa o un vettore non sapresti se usare first o second o semplicemente accedere direttamente alle proprietà dell'oggetto, no?

Questo mi ricorda il dibattito in C # sull'opportunità di utilizzare la parola chiave var . L'impressione che sto ottenendo è che nel mondo C ++ le persone sono pronte ad adottare la parola chiave auto con meno di una lotta rispetto a var nel mondo C #. Per me il mio primo istinto è che mi piace conoscere il tipo di variabile in modo da sapere quali operazioni posso aspettarmi di eseguire su di essa.

    
posta User 12.05.2012 - 00:01
fonte

6 risposte

36

Le motivazioni in C ++ sono più estreme, poiché i tipi possono diventare molto più complicati e complessi dei tipi C # a causa della metaprogrammazione e di altre cose. auto è più veloce da scrivere e leggere e più flessibile / manutenibile rispetto a un tipo esplicito. Voglio dire, vuoi iniziare a digitare

boost::multi_map<NodeType, indexed_by<ordered_unique<identity<NodeType>>, hashed_non_unique<identity<NodeType>, custom_hasher>>::iterator_type<0> it

Questo non è nemmeno il tipo completo. Ho perso un paio di argomenti del modello.

    
risposta data 12.05.2012 - 00:46
fonte
28

Nel tuo esempio:

for(auto it = x.begin(); it != x.end(); i++)
{
  it->??
}

ci deve essere una dichiarazione per x visibile. Pertanto il tipo di it dovrebbe essere ovvio. Se il tipo di x non è ovvio, il metodo è troppo lungo o la classe è troppo grande.

    
risposta data 12.05.2012 - 00:35
fonte
14

Obiezione ! Domanda caricata.

Puoi spiegarmi perché il terzo codice ha ?? in esso, eppure il primo e il secondo no? Per correttezza, il tuo codice deve leggere come segue:

for(std::vector<T>::iterator it = x.begin(); it != x.end(); i++)
{
   it->???
}

for(std::map<T>::iterator it = x.begin(); it != x.end(); i++)
{
   it->second->???
}

. Lo stesso problema anche se non hai utilizzato auto .

E in tutti i casi, la risposta è la stessa: Il contesto conta . Non si può parlare in modo significativo di un pezzo di codice in isolamento. Anche se non avessi usato i template ma qualche tipo concreto, questo avrebbe solo spostato il problema da qualche altra parte, poiché il lettore del tuo codice avrebbe dovuto conoscere la dichiarazione di quel tipo.

Se l'uso di auto in queste situazioni rende il tuo codice illeggibile, dovresti considerare questo come un segnale di avvertimento che c'è qualcosa di sbagliato nella progettazione del codice. Ovviamente, vi sono casi in cui i dettagli di basso livello sono importanti (ad esempio quando si gestiscono operazioni bit o API legacy) nei casi in cui un tipo esplicito potrebbe facilitare la leggibilità. Ma in generale - no.

Per quanto riguarda var (dato che lo hai esplicitamente menzionato), c'è anche un vasto consenso nella comunità C # per utilizzando var . Gli argomenti contro il suo utilizzo sono generalmente costruiti su errori .

    
risposta data 13.05.2012 - 15:10
fonte
11

PRO

Il tuo codice:

for(std::vector<T>::iterator it = x.begin(); it != x.end(); i++)

non verrà compilato, a causa del nome dipendente dal modello.

Questa è la sintassi corretta:

for( typename std::vector<T>::iterator it = x.begin(); it != x.end(); i++)

Ora guarda per quanto tempo è la dichiarazione del tipo. Questo indica perché è stata introdotta la parola chiave auto . Questo:

for( auto it = x.begin(); it != x.end(); i++)

è più conciso. Quindi, questo è un professionista.

CON

Devi essere un po 'attento. Con la parola chiave auto , ottieni il tipo che hai dichiarato.

Ad esempio:

std::vector< int > v{ 1, 2, 3, 4 };
for ( auto it : v )
{
  ++ it;   // ops modifying copies of vector's elements
}

vs

std::vector< int > v{ 1, 2, 3, 4 };
for ( auto & it : v )   // mind the reference
{
  ++ it;   // ok, vector's elements modified
}

Per concludere: sì, dovresti farlo, ma non esagerare. Alcune persone tendono ad usarlo troppo e mettono l'auto ovunque, come nel prossimo esempio:

auto i = 0;

vs

int i = 0;
    
risposta data 17.03.2014 - 10:11
fonte
6

SÌ, dovresti! auto non cancella il tipo; anche se "non sai" che cos'è x.begin() , il compilatore lo sa e segnalerà un errore se tenti di usare il tipo in modo errato. Inoltre, non è insolito emulare map con vector<pair<Key,Value>> , quindi il codice che utilizza auto funzionerà per entrambe le rappresentazioni del dizionario.

    
risposta data 13.05.2012 - 11:01
fonte
4

Sì, dovresti usare auto come regola predefinita. Presenta i vantaggi principali rispetto alla specifica esplicita del tipo:

  • Non ti fa scrivere cose di cui il compilatore è già al corrente.
  • Rende il tipo di variabili "segue" qualsiasi modifica nei tipi di valore di ritorno.
  • In questo modo, impedisce l'introduzione silenziosa di conversioni implicite e slicing nell'inizializzazione di variabili locali.
  • Rimuove la necessità di alcuni calcoli di tipo esplicito nei modelli.
  • Rimuove la necessità di assegnare un nome ai tipi di ritorno con nomi lunghi. (quelli che si copiano e incollano dalla diagnostica del compilatore)

Qui puoi scegliere. Ci sono anche casi in cui non hai una scelta:

  • Permette la dichiarazione di variabili di tipi non modificabili, come il tipo di lambda.

A condizione che tu sappia esattamente cosa fa auto , non ha svantaggi.

    
risposta data 02.10.2015 - 09:57
fonte

Leggi altre domande sui tag