auto
kann die Leistung verbessern, indem stille implizite Konvertierungen vermieden werden . Ein Beispiel, das mich überzeugt, ist das folgende.
std::map<Key, Val> m;
// ...
for (std::pair<Key, Val> const& item : m) {
// do stuff
}
Sehen Sie den Fehler? Hier denken wir, dass wir jedes Element in der Karte elegant als Konstantenreferenz nehmen und den neuen Bereich-für-Ausdruck verwenden, um unsere Absicht klar zu machen, aber tatsächlich kopieren wir jedes Element. Dies liegt daran std::map<Key, Val>::value_type
ist std::pair<const Key, Val>
, nicht std::pair<Key, Val>
. Wenn wir also (implizit) haben:
std::pair<Key, Val> const& item = *iter;
Anstatt einen Verweis auf ein vorhandenes Objekt zu nehmen und es dabei zu belassen, müssen wir eine Typkonvertierung durchführen. Sie dürfen einen konstanten Verweis auf ein Objekt (oder ein temporäres Objekt) eines anderen Typs erstellen, solange eine implizite Konvertierung verfügbar ist, z.
int const& i = 2.0; // perfectly OK
Die Typkonvertierung ist eine zulässige implizite Konvertierung aus demselben Grund, aus dem Sie a const Key
in a konvertieren können. Key
Wir müssen jedoch eine temporäre Konvertierung des neuen Typs erstellen, um dies zu ermöglichen. Somit macht unsere Schleife effektiv:
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
(Natürlich gibt es eigentlich kein __tmp
Objekt, es dient nur zur Veranschaulichung, in Wirklichkeit ist das unbenannte Temporär nur item
für seine Lebensdauer gebunden ).
Einfach ändern zu:
for (auto const& item : m) {
// do stuff
}
Wir haben gerade eine Menge Kopien gespeichert - jetzt stimmt der Typ, auf den verwiesen wird, mit dem Initialisierungstyp überein, sodass keine temporäre oder Konvertierung erforderlich ist. Wir können nur eine direkte Referenz erstellen.