右值引用
lvalue 是loactor value
的缩写,rvalue 是 read value
的缩写
https://subingwen.cn/cpp/rvalue-reference/
右值与左值
- 左值是指存储在内存中、有明确存储地址(可取地址)的数据;
- 右值是指可以提供数据值的数据(不可取地址)
纯右值
:非引用返回的临时变量、运算表达式产生的临时变量、原始字面量和 lambda 表达式等
将亡值
:与右值引用相关的表达式,比如,T&&类型函数的返回值、 std::move 的返回值等。
引用初始化
- 右值引用
- 只能用右值初始化右值引用 右值引用不用初始化右值引用
- 右值引用 本质是一个 左值
- 左值引用
- 常量右值引用
- 常量左值引用 万能引用类型
- 可以由左值、左值引用、右值引用、常量右值引用初始化
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| int num = 9;
int& a = num;
int&& b = 8;
const int&& d = 6;
const int& c = num; const int& f = b; const int& g = d; const int&h = a;
|
T&& auto&&
- 通过右值推导 T&& 或者 auto&& 得到的是一个右值引用类型
- 通过非右值(右值引用、左值、左值引用、常量右值引用、常量左值引用)推导 T&& 或者 auto&& 得到的是一个左值引用类型
1 2 3 4 5 6 7 8
| template<typename T> void f(T&& param); void f1(const T&& param); f(10); int x = 10; f(x); f1(x); f1(10);
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| int&& a1 = 5; auto&& bb = a1; auto&& bb1 = 5;
int a2 = 5; int &a3 = a2; auto&& cc = a3; auto&& cc1 = a2;
const int& s1 = 100; const int&& s2 = 100; auto&& dd = s1; auto&& ee = s2;
const auto&& x = 5;
|
move & forward
move
将左值转换为一个右值 用于去初始化右值引用
move与移动构造的区别
- move是将一个对象的所有权转给另一个对象 即对象的内容完全重复利用
- 移动构造 是在内部重写逻辑 复用堆区的内容 只是复用堆区内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| class Test { public: Test() : m_num(new int(100)) { cout << "construct: my name is jerry" << endl; }
Test(const Test& a) : m_num(new int(*a.m_num)) { cout << "copy construct: my name is tom" << endl; }
Test(Test&& a) : m_num(a.m_num) { a.m_num = nullptr; cout << "move construct: my name is sunny" << endl; }
~Test() { delete m_num; cout << "destruct Test class ..." << endl; }
int* m_num; };
|
move使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| #include <iostream> using namespace std;
class Test { public: Test() : m_num(new int(100)) { cout << "construct: my name is jerry" << endl; }
Test(const Test& a) : m_num(new int(*a.m_num)) { cout << "copy construct: my name is tom" << endl; }
Test(Test&& a) : m_num(a.m_num) { a.m_num = nullptr; cout << "move construct: my name is sunny" << endl; }
~Test() { delete m_num; cout << "destruct Test class ..." << endl; }
int* m_num; };
Test getObj() { Test t; return t; }
Test getObj1() { return Test(); }
int main() { Test t = getObj(); Test&& t1 = getObj(); Test&& t2 = getObj1(); Test&& t3 = move (t2) ; Test&& t4 = move(t) ; return 0; };
|
forward
右值引用作为值传递时 会成为一个左值引用
https://subingwen.cn/cpp/move-forward/
1 2 3 4 5 6
| template <class T> T&& forward (typename remove_reference<T>::type& t) noexcept; template <class T> T&& forward (typename remove_reference<T>::type&& t) noexcept;
std::forward<T>(t);
|
当T为左值引用类型时,t将被转换为T类型的左值
当T不是左值引用类型时,t将被转换为T类型的右值