Rvalue-ссылка &&
Rvalue-ссылка && - это специальный тип ссылки,
который привязывается к rvalue-выражениям, то есть
к временным объектам и объектам, которые можно
переместить. Обычная lvalue-ссылка & привязывается
к именованным объектам, которые имеют постоянный адрес
в памяти, а rvalue-ссылка && - к временным значениям,
которые живут только до конца выражения. Rvalue-ссылки
позволяют реализовать семантику перемещения и
идеальную передачу параметров.
Главное отличие rvalue-ссылки от lvalue-ссылки
заключается в том, что && может принимать
временные объекты, например результат работы
функции, литералы или результат арифметических
операций. При этом сама переменная, объявленная
как rvalue-ссылка, является lvalue, так как у неё
есть имя и адрес.
Синтаксис
type&& name = expression;
Пример
Давайте объявим rvalue-ссылку на целое число и выведем его значение:
#include <iostream>
using namespace std;
int main()
{
int&& ref = 123;
cout << ref << endl;
return 0;
}
Результат выполнения кода:
123
Обычная lvalue-ссылка int& не смогла бы
привязаться к литералу 123, потому что
литерал является rvalue-выражением.
Пример
Давайте создадим строку и привяжем rvalue-ссылку к результату её изменения:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str = "abcde";
string&& ref = str + "12345";
cout << ref << endl;
return 0;
}
Результат выполнения кода:
"abcde12345"
Пример
Давайте рассмотрим перегрузку функции для lvalue-ссылки и rvalue-ссылки, чтобы увидеть, какая версия вызывается:
#include <iostream>
using namespace std;
void func(int& value)
{
cout << "lvalue: " << value << endl;
}
void func(int&& value)
{
cout << "rvalue: " << value << endl;
}
int main()
{
int num = 123;
func(num);
func(456);
return 0;
}
Результат выполнения кода:
"lvalue: 123"
"rvalue: 456"
При передаче переменной num вызывается
версия функции с lvalue-ссылкой, а при передаче
литерала 456 - версия с rvalue-ссылкой.
Пример
Давайте используем функцию move, чтобы
преобразовать lvalue в rvalue и вызвать
перемещающий конструктор:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str = "abcde";
string&& ref = move(str);
cout << ref << endl;
cout << str << endl;
return 0;
}
Результат выполнения кода:
"abcde"
После вызова move исходная строка str
становится пустой, так как её содержимое было
перемещено во временный объект, на который
ссылается rvalue-ссылка ref.
Смотрите также
-
тип
lvalue-ref,
который описывает обычные ссылки -
тип
pointer,
который хранит адрес объекта -
тип
int,
который хранит целые числа -
тип
void,
который обозначает отсутствие типа