auto
peut améliorer les performances en évitant 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 le bug? Nous voici, pensant que nous prenons élégamment chaque élément de la carte par référence const et utilisons la nouvelle expression range-for pour clarifier notre intention, mais en réalité nous copions chaque élément. En effet , std::map<Key, Val>::value_type
est std::pair<const Key, Val>
, non 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 de le laisser là, nous devons faire une conversion de type. Vous êtes autorisé à prendre une référence const à un objet (ou temporaire) d'un type différent tant qu'une conversion implicite est disponible, par exemple:
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 const Key
en un Key
, mais nous devons construire un temporaire du nouveau type afin de permettre cela. Ainsi, effectivement, notre boucle:
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 d' __tmp
objet, il est juste là pour l'illustration, en réalité le temporaire sans nom est juste lié à item
sa durée de vie).
Je change simplement en:
for (auto const& item : m) {
// do stuff
}
vient de nous sauver une tonne de copies - maintenant le type référencé correspond au type d'initialisation, donc aucun temporaire ou conversion n'est nécessaire, nous pouvons simplement faire une référence directe.