auto
może poprawić wydajność, unikając cichych niejawnych konwersji . Przykład, który uważam za przekonujący, jest następujący.
std::map<Key, Val> m;
// ...
for (std::pair<Key, Val> const& item : m) {
// do stuff
}
Widzisz błąd? Oto my, myśląc, że elegancko bierzemy każdy element na mapie przez odniesienie do stałej i używamy nowego wyrażenia zakresu dla wyrażenia naszej intencji, ale w rzeczywistości kopiujemy każdy element. To dlatego, że std::map<Key, Val>::value_type
jest std::pair<const Key, Val>
, nie std::pair<Key, Val>
. Zatem gdy (domyślnie) mamy:
std::pair<Key, Val> const& item = *iter;
Zamiast odwoływać się do istniejącego obiektu i pozostawić go przy tym, musimy wykonać konwersję typu. Możesz wziąć stałe odniesienie do obiektu (lub tymczasowego) innego typu, o ile dostępna jest niejawna konwersja, np .:
int const& i = 2.0; // perfectly OK
Konwersja typu jest dozwoloną niejawną konwersją z tego samego powodu, dla którego można przekonwertować a const Key
na Key
, ale musimy skonstruować tymczasowy nowy typ, aby na to pozwolić. Zatem skutecznie nasza pętla:
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
(Oczywiście, nie ma w rzeczywistości żadnego __tmp
przedmiotu, jest tylko dla ilustracji, w rzeczywistości nienazwany tymczasowy jest po prostu związany z item
jego życiem).
Zmieniam się na:
for (auto const& item : m) {
// do stuff
}
właśnie zaoszczędziliśmy nam mnóstwo kopii - teraz typ odniesienia odpowiada typowi inicjalizującemu, więc nie jest potrzebna tymczasowa ani konwersja, możemy po prostu zrobić bezpośrednie odniesienie.