Ответ 1
Какие преимущества дает последняя форма над первым?
В форме for(auto& v : vector)
тип v
выводится как ссылка lvalue на тип, полученный разыменованием типа итератора контейнера. Это означает, что если результатом разыменования итератора является rvalue (подумайте std::vector<bool>
, который возвращает тип прокси, представляющий ссылку на одно значение bool
), тогда код не сможет скомпилироваться, поскольку ссылка lvalue не может связываться с rvalue.
Когда вы пишете for(auto&& v : vector)
, это универсальная ссылка, означающая, что тип v
будет выведен как ссылка rvalue в случае, описанном выше; или как ссылка lvalue в обычном случае, когда разыменование итератора возвращает ссылку на элемент контейнера. Таким образом, он работает и в случае vector<bool>
. Именно поэтому эта форма должна быть предпочтительной, если вы планируете модифицировать элементы, которые вы повторяете в цикле.
Почему мы обычно ходим с
auto&
вместоauto&&
, если последнее явно выгодно?
Вы не должны. Единственный недостаток, который я могу придумать auto&&
, заключается в том, что он не гарантирует, что изменения, внесенные вами в элементы, обязательно будут распространяться обратно в контейнер, но это свидетельствует о сломанном дизайне, и я не думаю, что он стоит защитить против.
Является ли создание нового цикла, основанного на диапазоне, равным
auto &&
, чтобы сломать существующий код?
Я не вижу, как он может сломать существующий код, потому что старый синтаксис будет продолжать функционировать так же, как сегодня. Но если вы хотите заменить существующий код новым синтаксисом, то он может иметь эффект, если тот, который вы заменяете, это форма auto const&
. См. этот пример. Обратите внимание на то, как версия auto const&
вызывает функцию члена const
, а две другие - версию не const
? Замена первой с помощью краткой версии приведет к изменению вызываемой функции-члена.
Будет ли это иметь реальное влияние на новый код?
Опять же, он не отличается от старого кода, который использует auto&&
сегодня, так что не будет видно разницы. Если вы используете его в тех местах, где вы не собираетесь изменять элементы, то компилятор больше не остановит вас от этого, и вы можете вызвать другую перегрузку, как показано в примере выше.
Разве это не означало бы, что их код на самом деле эквивалентен
auto &&
?
Я не уверен, что понимаю, что вы подразумеваете под этим, но если вы спрашиваете, будут ли новички писать код, не зная, или понимая, что запутанность ссылок рушится, тогда да, возможно, они это сделают. Но это одна из заявленных целей документа, с которым вы связались. Аргумент заключается в том, что вы можете держаться подальше от обучения этим сложным понятиям прямо на ходу, но вводите новичков в один синтаксис для циклов for
на основе диапазона, который работает со всем. Что касается этого, я думаю, что синтаксис имеет смысл, но, глядя на него с точки зрения правильности const
, я на него нахмурился, потому что я предпочел бы использовать auto const&
, если я хочу доступ только для чтения к элементам, и тогда краткий синтаксис кажется асимметричным.