Принудительное автоматическое задание типа ссылки в диапазоне для цикла
Предположим, что у меня есть foo
, который является заполненным std::vector<double>
.
Мне нужно оперировать элементами этого вектора. Я мотивирован писать
for (auto it : foo){
/*ToDo - Operate on 'it'*/
}
Но похоже, что это не будет возвращаться к foo
, так как it
- тип значения: была сделана глубокая копия векторного элемента.
Могу ли я дать некоторые указания auto
сделать it
ссылочным типом? Тогда я мог бы работать непосредственно на it
.
Я подозреваю, что мне не хватает тривиального синтаксиса.
Ответы
Ответ 1
Минимальная auto
ссылка
Цикл может быть объявлен следующим образом:
for (auto& it : foo) {
// ^ the additional & is needed
/*ToDo - Operate on 'it'*/
}
Это позволит it
быть ссылкой на каждый элемент в foo
.
Есть некоторые дебаты относительно "канонической формы" этих циклов, но auto&
должен сделать трюк в этом случае.
Общая auto
ссылка
В более общем смысле (вне специфики контейнера) следующий цикл работает (и может быть предпочтительным).
for (auto&& it : container) {
// ^ && used here
}
auto&&
позволяет привязки к значениям и значениям. При использовании в общей или общей (например, ситуации с шаблоном) эта форма может нанести желаемый баланс (например, ссылки, копии, возврат значения/значения ценности (например, прокси-объекты) и т.д.).
Благодарите за общее auto&&
, но если вы должны быть конкретным относительно формы, используйте более конкретный вариант (например, auto
, auto const&
и т.д.).
Почему auto&&
лучше?
Как отмечено в других ответах здесь и в комментариях. Почему auto&&
лучше? Просто он будет делать то, что, по вашему мнению, должно быть в большинстве случаев, см. это предложение и его обновление.
Как всегда, blog об этом также делает хорошее чтение.
Ответ 2
Я бы использовал auto&&
:
for (auto&& it : foo) {
// bla
}
Причина изложена в N3994 "Диапазоны for-Loops: следующее поколение (версия 1)" что лучше работать с прокси-объектами (такими как те, которые идут от std::vector<bool>
).
Фактически, это предложение для С++ 1z (поддерживается уже Clang 3.5 SVN в режиме -std=c++1z
) предлагает синтаксис:
// c++1z only
for (it : foo) {
// bla
}
в качестве короткой руки для for (auto&& it : foo)
.
Обновить: предложение N3994 было не проголосовало в рабочем документе С++ 17.
Ответ 3
Вы можете использовать:
for (auto&& it : foo){
}
auto &&
предпочитает auto &
управлять итератором прокси-сервера, как и для std::vector<bool>
.
Ответ 4
Во многом это путаница возникает из конвенции, которая выросла на протяжении многих лет, чтобы привязать *
или &
к типу в отличие от переменной.
Например int* a
действительно int *a
; т.е. a
является указателем на значение типа int
.
То же самое относится к ссылкам: в случае int& a
, a
является ссылкой на значение типа int
.
Итак, что вы действительно хотите сделать, это написать for (auto &it : foo)
, поэтому it
является ссылкой на тип, выводимый auto
. Затем вы можете использовать it
для управления базовыми векторными элементами. Чаще всего это будет написано как
for (auto& it : foo)
Двигаясь вперед, вы можете использовать ссылку r-value: for (auto&& it : foo)
, которая, вероятно, является наилучшей общей формой.