Какая разница между обычной ссылкой 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
всегда возвращает ссылку rvalue, как ссылка, возвращаемая std::forward
отличается от int&&q
?
Ответы
Ответ 1
как ссылка, возвращаемая std::forward
отличается от int&&q
?
Их категории значений разные. И обратите внимание, что типы и категории значений - это разные вещи.
q
- именованная переменная, она квалифицируется как lvalue, поэтому она не может быть привязана к ссылке rvalue.
(акцент мой)
имя переменной, функцию, объект параметра шаблона (начиная с С++ 20) или элемент данных независимо от типа, например std::cin
или std::endl
. Даже если тип переменной является ссылкой rvalue, выражение, состоящее из его имени, является выражением lvalue;
В то время как ссылка rvalue, возвращаемая функцией, квалифицируется как xvalue, которая принадлежит rvalue.
вызов функции или перегруженное операторное выражение, возвращаемым типом которого является rvalue ссылка на объект, например std::move(x)
;
Ответ 2
Разница между выражениями q
и std::forward<int>(q)
заключается в том, что первая является lvalue, а последняя является rvalue (фундаментальной категории xvalue).
Я обратился к подобным проблемам в этом ответе: дело в том, что q
как выражение является lvalue, потому что оно имеет имя. std::forward<int>(q)
(или эквивалентный std::move(q)
) - это выражения, которые не имеют имен, а так как они возвращают (неназванные) ссылки rvalue, они являются значениями x, что является подкатегорией rvalue и, таким образом, может привязываться к ссылке rvalue.