auto
peut contribuer aux performances en éviter les conversions implicites silencieuses . Un exemple que je trouve convaincant est le suivant.
std::map<Key, Val> m;
// ...
for (std::pair<Key, Val> const& item : m) {
// do stuff
}
Vous voyez l'insecte ? Nous sommes là, pensant que nous prenons élégamment chaque élément de la carte par référence constante et que nous utilisons la nouvelle expression range-for pour rendre notre intention claire, mais en fait nous copions chaque élément. Cela est dû au fait que std::map<Key, Val>::value_type
es std::pair<const Key, Val>
pas std::pair<Key, Val>
. Ainsi, lorsque nous avons (implicitement) :
std::pair<Key, Val> const& item = *iter;
Au lieu de prendre une référence à un objet existant et d'en rester là, nous devons effectuer une conversion de type. Vous êtes autorisé à prendre une référence const vers un objet (ou temporaire) d'un type différent tant qu'il existe une conversion implicite disponible, par ex :
int const& i = 2.0; // perfectly OK
La conversion de type est une conversion implicite autorisée pour la même raison que vous pouvez convertir un fichier const Key
à un Key
mais nous devons construire un temporaire du nouveau type afin de le permettre. Donc, effectivement, notre boucle fait :
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
(Bien sûr, il n'y a pas réellement de __tmp
il est juste là pour l'illustration, en réalité le temporaire sans nom est juste lié à l'objet item
pour sa durée de vie).
Je change juste pour :
for (auto const& item : m) {
// do stuff
}
vient de nous épargner une tonne de copies - maintenant le type référencé correspond au type de l'initialisateur, donc aucun temporaire ou conversion n'est nécessaire, nous pouvons juste faire une référence directe.