Читая некоторые примеры циклов на основе диапазона, они предлагают два основных способа 1 , 2 , 3 , 4
std::vector<MyClass> 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
}
Хорошо.
Когда нам не нужно менять vec
предметы, 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
?
const auto &x
эквивалентно вашему третьему выбору.auto&&
когда вы не хотите делать ненужную копию, и вам все равно, измените ли вы ее или нет, и вы хотите просто работать.const
наверняка. Тем не менее, будь тоauto const &
, илиauto const
будет мало разницы. Я бы выбралauto const &
просто быть более последовательным.Если у вас есть
std::vector<int>
илиstd::vector<double>
, тогда лучше использоватьauto
вместо него (со значением copy)const auto&
, так как копированиеint
или этоdouble
дешево:Но если у вас есть
std::vector<MyClass>
, гдеMyClass
есть некоторая нетривиальная семантика копирования (напримерstd::string
, некоторый сложный пользовательский класс и т. Д.), Тогда я бы предложил использовать,const auto&
чтобы избежать глубоких копий :источник
Тогда они дают неверное предложение.
Потому что они дают неверное предложение :-) То, что вы упоминаете, является правильным. Если вы хотите только наблюдать за объектом, вам не нужно создавать копию, и нет необходимости иметь
const
ссылку на него.РЕДАКТИРОВАТЬ:
Я вижу, что ссылки, на которые вы ссылаетесь, содержат примеры итерации по диапазону
int
значений или некоторому другому фундаментальному типу данных. В этом случае, поскольку копирование неint
является дорогостоящим, создание копии в основном эквивалентно (если не более эффективно, чем) наблюдениюconst &
.Однако в общем случае это не относится к пользовательским типам. Копирование UDT может быть дорогостоящим, и если у вас нет причины для создания копии (например, изменение извлеченного объекта без изменения исходного), то предпочтительно использовать
const &
.источник
Я собираюсь быть противоположным здесь и сказать, что нет необходимости
auto const &
в диапазоне, основанном на цикле. Скажите, если вы думаете, что следующая функция глупа (не по назначению, а по тому, как она написана):Здесь автор создал константную ссылку на
v
использование для всех операций, которые не изменяют v. На мой взгляд, это глупо, и такой же аргумент можно использовать для использованияauto const &
в качестве переменной в диапазоне, основанном на цикле вместо простоauto &
,источник
const_iterator
в цикле for? Как вы гарантируете, что не меняете исходные элементы из контейнера, когда выполняете итерации по нему?const_iterator
? Позвольте мне угадать, контейнер, над которым вы перебираете, естьconst
. Но с чего этоconst
начать? Где вы используете,const
чтобы убедиться, что?const
подобно преимуществам использованияprivate
/protected
в классах. Это позволяет избежать дальнейших ошибок.v
, реализация была бы хорошей IMO. И если цикл никогда не изменяет объекты, через которые он проходит, мне кажется правильным иметь ссылку наconst
. Я понимаю вашу точку зрения, хотя. Мое состоит в том, что цикл представляет кодовую единицу почти так же, как функция, и внутри этой единицы нет инструкции, которая должна изменить значение. Таким образом, вы можете «пометить» весь блок так жеconst
, как вы бы сделали сconst
функцией-членом.const &
основанный на диапазоне - это глупо, потому что вы написали неуместный воображаемый пример воображаемого программиста, который сделал что-то глупое с cv -qualification? ... Хорошо, тогда