// 左值
int a; // 变量
vector<int> buf; // 对象
"sss"; // 字符串常量
// 右值
10;
string(); vector<int>(); // 匿名对象
右值引用就是给右值(将亡值)取别名,然后当我们用将亡值来进行拷贝或赋值时可以把 this 对象和将亡值的内容进行交换,以此减少拷贝次数,增加拷贝效率。
一般的左值引用确实不能引用右值,但 const 的左值引用既可以引用左值,也可以引用右值;然而,右值引用只能引用右值,但其实也可以通过 move() 函数引用左值。
移动语义其实就是把两个对象之间的内容进行交换,来减少拷贝次数的原理。
可以看成是一个把左值传进去,然后返回右值的函数。
template<typename T>
void func(T&& t) // 注:"T&&" 是万能引用,不是右值引用
{
Func(t);
}
万能引用既能接受左值,也能接受右值。当且仅当 func() 是函数模板时,T&& 表示的就是万能引用,不是右值引用。当实参是左值时,&& 就会自动折叠成 &(俗称“引用折叠”),当实参是右值时,&& 不会进行折叠。
首先,我们可以跑一跑下面的代码:
void Fun(int& x) { cout << "lvalue ref" << endl; }
void Fun(int&& x) { cout << "rvalue ref" << endl; }
void Fun(const int& x) { cout << "const lvalue ref" << endl; }
void Fun(const int&& x) { cout << "const rvalue ref" << endl; }
template<typename T>
void PerfectForward(T&& t)
{
Fun(t);
}
int main()
{
PerfectForward(10);
int a;
PerfectForward(a);
PerfectForward(std::move(a));
const int b = 8;
PerfectForward(b);
PerfectForward(std::move(b));
return 0;
}
如果结果都是左值引用,别感到奇怪,因为在 PerfectForward() 函数里面, 无论实参是右值还是左值, 进来 PerfectForward() 后都会有一个变量名——t。而当这个对象有了变量名,这个对象在这个函数作用域里就是左值了,即使它原本是右值。因此就会导致右值一旦进入一个函数就会悄悄地变成左值,而这是不好的。因此,为了保持对象在函数传参时左右值属性不变,C++便引入了完美转发。 或者也可以这么说,完美转发一般都是与万能引用搭配使用的。
完美转发的作用就是保持函数形参的左右值属性。
以上面的代码为例,如果 t 原本是右值传进来的,那么经过完美转发后,t 还会是右值;而如果 t 原本是左值传进来的,那么通过完美转发后 t 还会是左值。
C++的完美转发就是通过 std::forward<T>() 函数来实现的。
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- huatuoyibo.net 版权所有 湘ICP备2023021910号-2
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务