const auto&
было бы достаточно, если я хочу выполнять операции только для чтения. Однако я наткнулся на
for (auto&& e : v) // v is non-const
пару раз за последнее время. Это заставляет меня задуматься:
Возможно ли, что в некоторых непонятных угловых случаях есть некоторое преимущество в производительности при использовании ссылок пересылки по сравнению с auto&
или const auto&
?
( shared_ptr
подозревается в неясных делах)
Обновление Два примера, которые я нашел в своих избранных:
Есть ли недостаток использования константной ссылки при итерации по базовым типам?
Могу ли я легко перебирать значения карты, используя цикл for на основе диапазона?
Пожалуйста, сконцентрируйтесь на вопросе: зачем мне использовать auto && в циклах на основе диапазона?
auto&&
циклы for на основе диапазона?Ответы:
Единственное преимущество, которое я вижу, - это когда итератор последовательности возвращает ссылку на прокси, и вам нужно работать с этой ссылкой неконстантным способом. Например, рассмотрим:
Это не компилируется, потому что rvalue,
vector<bool>::reference
возвращаемое изiterator
, не будет привязываться к неконстантной ссылке lvalue. Но это сработает:При этом я бы не стал кодировать таким образом, если бы вы не знали, что вам нужно удовлетворить такой вариант использования. То есть я бы не стал делать это бесплатно, потому что это заставляет людей задуматься, чем вы занимаетесь . И если бы я это сделал, не помешало бы добавить комментарий, почему:
редактировать
Этот последний мой случай действительно должен быть шаблоном, чтобы иметь смысл. Если вы знаете, что цикл всегда обрабатывает ссылку на прокси-сервер, то он
auto
будет работать так же хорошо, какauto&&
. Но когда цикл иногда обрабатывал непрокси-ссылки, а иногда и прокси-ссылки, я думаю,auto&&
это стало бы предпочтительным решением.источник
const auto&
когда хочу, чтобы компилятор помог мне проверить, случайно ли я не изменил элементы в последовательности.auto&&
общий код, когда мне нужно изменить элементы последовательности. Если нет, я просто буду придерживатьсяauto const&
.Использование
auto&&
или универсальные ссылки с диапазоном на основеfor
-loop имеет то преимущество , что вы улавливает то , что вы получите. Для большинства типов итераторов вы, вероятно, получите либо a,T&
либо aT const&
для некоторого типаT
. Интересен случай, когда разыменование итератора приводит к временному результату: C ++ 2011 имеет ослабленные требования, и итераторы не обязательно требуются для получения lvalue. Использование универсальных ссылок соответствует пересылке аргументов вstd::for_each()
:Объект функции
f
может лечитьT&
,T const&
и по-T
другому. Почему тело цикла на основеfor
диапазона должно отличаться? Конечно, чтобы на самом деле воспользоваться выводом типа с помощью универсальных ссылок, вам нужно будет передать их соответственно:Конечно, использование
std::forward()
означает, что вы принимаете любые возвращаемые значения для перемещения. Имеют ли такие объекты смысл в коде, отличном от шаблона, я не знаю (пока?). Я могу себе представить, что использование универсальных ссылок может дать компилятору больше информации, чтобы сделать правильный выбор. В шаблонном коде он не принимает никакого решения о том, что должно происходить с объектами.источник
Практически всегда пользуюсь
auto&&
. Зачем вас укусил крайний случай, когда в этом нет необходимости? Он тоже короче, и я просто считаю его более ... прозрачным. Когда вы используетеauto&& x
, то знаете, чтоx
это точно*it
, каждый раз.источник
const
-ness с ,auto&&
еслиconst auto&
хватает. Вопрос касается угловых случаев, когда меня могут укусить. Какие крайние случаи еще не упомянули Дитмар или Ховард?auto&&
. Если тип, который вы захватываете, следует переместить в тело цикла (например) и изменить на более позднюю дату, чтобы он разрешился вconst&
тип, ваш код будет молча продолжать работу, но ваши ходы будут копиями. Этот код будет очень обманчивым. Если, однако, вы явно укажете тип как ссылку на r-значение, тот, кто изменил тип контейнера, получит ошибку компиляции, потому что вы действительно хотели, чтобы эти объекты перемещались, а не копировались ...for (std::decay_t<decltype(*v.begin())>&& e: v)
? Думаю, есть способ получше ...auto&&
это даст «универсальную ссылку», так что все, кроме этого, даст вам более конкретный тип. Еслиv
предполагается, что это avector
, вы можете сделать этоdecltype(v)::value_type&&
, как я полагаю, вы хотели, взяв результатoperator*
на типе итератора. Вы такжеdecltype(begin(v))::value_type&&
можете проверить типы итератора вместо контейнера. Если мы так мало разбираемся в типе, мы могли бы подумать, что будет немного понятнее просто пойти сauto&&
...