auto
può aiutare le prestazioni evitando conversioni implicite silenziose . Un esempio che trovo convincente è il seguente.
std::map<Key, Val> m;
// ...
for (std::pair<Key, Val> const& item : m) {
// do stuff
}
Vedi il bug? Eccoci qui, pensando che stiamo prendendo elegantemente ogni elemento nella mappa come riferimento costante e usando la nuova gamma-for expression per chiarire il nostro intento, ma in realtà stiamo copiando ogni elemento. Questo perché std::map<Key, Val>::value_type
è std::pair<const Key, Val>
, non è std::pair<Key, Val>
. Pertanto, quando (implicitamente) abbiamo:
std::pair<Key, Val> const& item = *iter;
Invece di prendere un riferimento a un oggetto esistente e lasciarlo a quello, dobbiamo fare una conversione di tipo. È consentito prendere un riferimento const a un oggetto (o temporaneo) di un tipo diverso purché sia disponibile una conversione implicita, ad esempio:
int const& i = 2.0; // perfectly OK
La conversione del tipo è una conversione implicita consentita per lo stesso motivo per cui è possibile convertire un const Key
in Key
, ma per consentirlo dobbiamo costruire un temporaneo del nuovo tipo. Pertanto, in modo efficace il nostro loop fa:
std::pair<Key, Val> __tmp = *iter; // construct a temporary of the correct type
std::pair<Key, Val> const& item = __tmp; // then, take a reference to it
(Certo, in realtà non c'è un __tmp
oggetto, è solo lì per l'illustrazione, in realtà il temporaneo senza nome è solo legato alla item
sua vita).
Sto solo cambiando in:
for (auto const& item : m) {
// do stuff
}
ci ha appena salvato un sacco di copie - ora il tipo a cui fa riferimento corrisponde al tipo di inizializzatore, quindi non è necessaria alcuna conversione temporanea, possiamo solo fare un riferimento diretto.