В чем разница между обычной ссылкой на rvalue и ссылкой, возвращаемой std :: forward?

Я не могу сделать это:

int &&q = 7;
int &&r = q;
//Error Message:
//cannot convert from 'int' to 'int &&'
//You cannot bind an lvalue to an rvalue reference

Если я правильно понимаю, при инициализации ссылки на rvalue есть инициализированная временная переменная. Так int &&q = 7; можно рассматривать как:

int temp = 7;
int &&q = temp;

И при использовании ссылки на правой стороне, я на самом деле использую рефери. Так int &&r = q; можно рассматривать как:

int &&r = temp;  //bind an lvalue to an rvalue reference, cause error, understandable

Итак, выше, как я понимаю, возникает ошибка компилятора.


Зачем добавлять std::forward может решить это?

int &&q = 7;
int &&r = std::forward<int>(q);

Я знаю std::forward всегда возвращает ссылку на значение, как ссылка возвращается std::forward отличный от int&&q?

17

Решение

как ссылка возвращается std::forward отличный от int&&q ?

Их категории значений разные. И обратите внимание, что типы и категории значений — это разные вещи.

q является именованной переменной, она квалифицируется как именующий, поэтому он не может быть привязан к rvalue ссылке.

(акцент мой)

имя переменной, функции, объекта параметра шаблона (начиная с C ++ 20) или члена данных, независимо от типа, такого как std::cin или же std::endl, Даже если тип переменной является ссылкой на rvalue, выражение, состоящее из ее имени, является выражением lvalue;

В то время как ссылка rvalue, возвращаемая из функции, квалифицируется как xvalue, который принадлежит Rvalue.

вызов функции или перегруженное выражение оператора, тип возвращаемого значения которого является rvalue ссылкой на объект, такой как std::move(x);

13

Другие решения

Разница между выражениями q а также std::forward<int>(q) является то, что первое является lvalue, в то время как второе является rvalue (фундаментальной категории xvalue).

Я обращался к аналогичным проблемам в этот ответ: Дело в том, что q как выражение является именующий, потому что у него есть имя. std::forward<int>(q) (или эквивалент std::move(q)) являются выражениями, которые не имеют имен, и, поскольку они возвращают (неназванные) ссылки на rvalue, они являются значениями xvalue, которые являются подкатегорией rvalue и, таким образом, могут связываться со ссылкой на rvalue.

10

По вопросам рекламы [email protected]