Цикл на основе C ++ 11: получить элемент по значению или ссылке на const

Читая некоторые примеры циклов, основанных на диапазонах, они предлагают два основных способа: 1 , 2 , 3 , 4

std::vector vec; for (auto &x : vec) { // x is a reference to an item of vec // We can change vec's items by changing x } 

или

 for (auto x : vec) { // Value of x is copied from an item of vec // We can not change vec's items by changing x } 

Что ж.

Когда нам не нужны переменные предметы, IMO, примеры предлагают использовать вторую версию (по значению). Почему они не предлагают то, что ссылается на const (по крайней мере, я не нашел прямого предложения):

 for (auto const &x : vec) // <-- see const keyword { // x is a reference to an const item of vec // We can not change vec's items by changing x } 

Разве это не лучше? Разве он не избегает избыточной копии на каждой итерации, пока она является const ?

Если вы не хотите изменять элементы, а также хотите избежать копирования, тогда auto const & является правильным выбором:

 for (auto const &x : vec) 

Тот, кто предлагает вам использовать auto & is wrong. Игнорируй их.

Вот резюме:

  • Выберите auto x когда вы хотите работать с копиями.
  • Выберите auto &x когда вы хотите работать с оригинальными элементами и можете их изменить.
  • Выберите auto const &x когда вы хотите работать с оригинальными элементами и не будете изменять их.

Если у вас есть std::vector или std::vector , тогда просто удобно использовать auto (со значением copy) вместо const auto& , так как копирование int или double дешево:

 for (auto x : vec) .... 

Но если у вас есть std::vector , где MyClass имеет некоторую нетривиальную семантику копирования (например, std::string , некоторый сложный пользовательский class и т. Д.), То я бы предложил использовать const auto& чтобы избежать глубоких копий :

 for (const auto & x : vec) .... 

Когда нам не нужны переменные элементы vec , в примерах предлагается использовать первую версию.

Затем они дают неправильное предложение.

Почему они не предлагают то, что ссылается на const

Потому что они дают неправильное предложение 🙂 То, что вы упоминаете, является правильным. Если вы хотите только наблюдать за объектом, нет необходимости создавать копию, и нет необходимости иметь ссылку на нее.

РЕДАКТИРОВАТЬ:

Я вижу ссылки, на которые вы ссылаетесь, приводят примеры итерации по диапазону значений int или некоторого другого фундаментального типа данных. В этом случае, поскольку копирование int не дорого, создание копии в основном эквивалентно (если не более эффективному), имеющему наблюдающий const & .

Это, однако, не в общем случае для пользовательских типов. UDT могут быть дорогими для копирования, и если у вас нет причин для создания копии (например, для изменения извлеченного объекта без изменения исходного), тогда предпочтительно использовать const & .

Я собираюсь быть противоположным здесь и сказать, что нет необходимости в auto const & в диапазоне, основанном на цикле. Скажите мне, считаете ли вы, что следующая функция глупа (не в своей цели, а в том, как она написана):

 long long SafePop(std::vector& v) { auto const& cv = v; long long n = -1; if (!cv.empty()) { n = cv.back(); v.pop_back(); } return n; } 

Здесь автор создал константную ссылку на v для использования для всех операций, которые не изменяют v. Это, на мой взгляд, глупо, и тот же аргумент может быть сделан для использования auto const & как переменной в диапазоне, основанном на а не просто auto & .

  • 😃 (и другие символы Unicode) в идентификаторах, недопустимых g ++
  • Является ли идиома safe-bool устаревшей в C ++ 11?
  • Разница между угловыми скобками и двойными кавычками "", включая заголовочные файлы в C ++?
  • Генерация случайных чисел в C ++ 11, как сгенерировать, как они работают?
  • Что такое std :: decay и когда он должен использоваться?
  • Сужение конверсий в C ++ 0x. Это только я, или это звучит как нарушение?
  • О том, как распознать ссылку Rvalue или Lvalue и правило if-it-have-a-name
  • Double-Checked Lock Singleton в C ++ 11
  • Visual Studio 2012 __cplusplus и C ++ 11
  • Связать Vs Лямбда?
  • Могут ли виртуальные функции иметь параметры по умолчанию?
  • Interesting Posts
    Давайте будем гением компьютера.