auto
може сприяти ефективності, уникаючи беззвучних неявних перетворень . Приклад, який я вважаю переконливим, наступний.
std::map<Key, Val> m;
// ...
for (std::pair<Key, Val> const& item : m) {
// do stuff
}
Бачите помилку? Ось ми, думаючи, що ми елегантно беремо кожен елемент на карті за допомогою посилання const та використовуємо новий діапазон для вираження, щоб зрозуміти наші наміри, але насправді ми копіюємо кожен елемент. Це тому, що std::map<Key, Val>::value_type
є std::pair<const Key, Val>
, ні std::pair<Key, Val>
. Таким чином, коли ми (неявно) маємо:
std::pair<Key, Val> const& item = *iter;
Замість того, щоб взяти посилання на існуючий об’єкт і не залишити його при цьому, ми повинні зробити перетворення типу. Вам дозволяється приймати посилання const на об'єкт (або тимчасовий) іншого типу до тих пір, поки наявна неявна конверсія, наприклад:
int const& i = 2.0; // perfectly OK
Перетворення типів - це дозволена неявна конверсія з тієї ж причини, яку ви можете перетворити в const Key
a Key
, але ми повинні побудувати тимчасовий нового типу, щоб дозволити це. Таким чином, ефективно наш цикл робить:
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
(Зрозуміло, насправді __tmp
об’єкта насправді немає , він просто є для ілюстрації, насправді неназваний тимчасовий якраз і зобов'язаний item
протягом життя).
Просто змінюється на:
for (auto const& item : m) {
// do stuff
}
щойно врятували нам тонну копій - тепер тип посилань відповідає типу ініціалізатора, тому тимчасове або перетворення не потрібно, ми можемо просто зробити пряме посилання.