Подтвердить что ты не робот

Принудительное автоматическое задание типа ссылки в диапазоне для цикла

Предположим, что у меня есть foo, который является заполненным std::vector<double>.

Мне нужно оперировать элементами этого вектора. Я мотивирован писать

for (auto it : foo){
   /*ToDo - Operate on 'it'*/
}

Но похоже, что это не будет возвращаться к foo, так как it - тип значения: была сделана глубокая копия векторного элемента.

Могу ли я дать некоторые указания auto сделать it ссылочным типом? Тогда я мог бы работать непосредственно на it.

Я подозреваю, что мне не хватает тривиального синтаксиса.

4b9b3361

Ответ 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), которая, вероятно, является наилучшей общей формой.