Разница между возвратом константной ссылки и rvalue-ссылки
Если я не ошибаюсь, я думаю, что и константная ссылка, и ссылка на rvalue могут связываться с rvalue. Есть ли практическая разница между функцией, которая возвращает первое, и функцией, которая возвращает второе?
РЕДАКТИРОВАТЬ. Я не могу изменить первое, но почему я заинтересован в изменении значения? Имеет ли это смысл?
2 ответа
const
Ссылка lvalue может связываться с чем угодно. Ссылка rvalue может связываться только с const
rvalues.
non-const lvalue const lvalue non-const rvalue const rvalue
const T& yes yes yes yes
T&& no no yes no
Как видите, они очень разные.
Кроме того, если вызов функции возвращает ссылку lvalue, это выражение является lvalue, но если вызов функции возвращает ссылку rvalue на объект, это выражение является значением xvalue.
Вызов функции является lvalue, если тип результата является ссылочным типом lvalue или ссылкой rvalue на тип функции, xvalue, если тип результата является ссылкой rvalue на тип объекта, и prvalue в противном случае.
Что касается того, когда вы захотите изменить rvalue - это именно то, что представляет собой семантика перемещения. Рассмотрим следующий вызов функции:
void func(std::string);
func(std::string("Hello"));
Выражение std::string("Hello")
это значение, которое создает временный объект. При инициализации std::string
параметр с этим rvalue, он выберет конструктор, который принимает ссылку на rvalue - конструктор перемещения. Затем этот конструктор крадет вещи из rvalue, что обычно намного быстрее, чем полная копия. Мы можем украсть его, потому что знаем, что это временно.
Что касается того, когда вы должны вернуться const
lvalue ссылки или rvalue ссылки:
Возвращение
const
Ссылка lvalue чаще всего используется, когда вы хотите предоставить доступ для чтения "внутреннего" объекта (возможно, члена класса), но не позволяете людям изменять его.Возвращение ссылки на rvalue чаще всего используется (вообще не используется), когда вы хотите разрешить вызывающему коду перемещаться из "внутреннего" объекта (возможно, члена класса). Таким образом, вместо перемещения от временно возвращаемого объекта (как при возврате по значению), они буквально перемещаются от внутреннего объекта.
Этого также можно достичь с помощью
const
lvalue ссылка, но тогда им придется явноstd::move
Это.
Поэтому маловероятно, что вам нужно будет возвращать ссылку на rvalue.
Не то std::forward
имеет тип возврата, который выглядит как T&&
, Тем не менее, это обманчиво, потому что это может или не может быть ссылкой на значение в зависимости от типа T
, Смотрите универсальные ссылки.
Есть ли практическая разница между функцией, которая возвращает первое, и функцией, которая возвращает второе?
Вопрос кажется плохо сформированным. Функция, которая возвращает константу lvalue-reference, обеспечивает доступ к объекту только для чтения, тогда как функция, которая возвращает rvalue-reference, обеспечивает доступ для перемещения, что означает, что вызывающая сторона может взять содержимое упомянутого объекта и переместить его в другой объект. объект. Они не сравнимы ни в коем случае.
В обоих случаях ссылки должны указывать на объект, время жизни которого выходит за пределы конца функции, которая его возвращает, иначе вызывающий вызов отключится с неопределенным поведением при использовании этой ссылки.