左值,右值,右值引用,std::ref(),std::reference_wrapper

中文标准库:值类别 | 值类别的翻译

转载:C++中的左值和右值 | 转载:C++中的右值引用和移动

一、左值(lvalue):

简单的来说,能取地址的变量一定是左值,有名字的变量也一定是左值,最经典的void fun(p&& shit),其中shit也是左值,因为右值引用是左值(所以才会有move,forward这些函数的产生,其中move出来一定是右值,forward保持变量形式和之前的不变,就是为了解决右值引用是左值的问题)。至于为什么不能把等号左边看成左值,因为在C++中,等号是可以运算符重载的,等号完全可以重载成为等号左边为右值的形式。

左值是可以取地址的,这也是区分左值和右值的唯一正确的标志

注意:字符串是左值,字面值常量是右值。例如:"Hello World!"是左值,666,9.9,true,false,nullptr都是纯右值

二、右值(rvalue):

当函数返回一个值时编译器会创建一个零时且完整的对象,这个对象就是一个右值

  • prvalue(纯右值):

纯右值是传统右值的一部分,纯右值是表达式产生的中间值,不能取地址

  • rvalue(右值):

和左值不同,右值不可以取地址,右值不能在内建等号的左边,如果运算符重载右值是可以在等号左边的

三、消亡值(xvalue):

本质上,消亡值就是通过右值引用产生的值。右值一定会在表达式结束后被销毁,比如return x(x被copy以后会被销毁), 1+2(3这个中间值会被销毁)。

四、右值引用

右值引用用&&表示,字面意思就是以引用传递(而非值传递)的方式使用右值

和声明左值引用一样,右值引用也必须立即进行初始化操作,且只能使用右值进行初始化,例如:

int num = 10;
//int && a = num;  //错误,右值引用不能初始化为左值
int && a = 10;

五、引用和std::ref以及std::cref

转载:std::move、std::ref和std::bind

std::ref只是尝试模拟引用传递,并不能真正变成引用,在非模板情况下,std::ref根本没法实现引用传递,只有模板自动推导类型时,ref能用包装类型reference_wrapper来代替原本会被识别的值类型,而reference_wrapper能隐式转换为被引用的值的引用类型。std::ref主要是考虑函数式编程如std::bind)在使用时,是对参数直接拷贝,而不是引用。比如thread的方法传递引用的时候,必须外层用ref来进行引用传递,否则就是浅拷贝。

std::ref用于包装按引用传递的值。std::cref用于包装按const引用传递的值

六、std::reference_wrapper

转载:引用传参与REFERENCE_WRAPPER

七、常引用、引用、传引用、传值

引用本质只是另一个对象的别名。对引用别名的操作即是对本身变量的操作。

常引用只能指向一个常量对象,不能指向另一个常量对象。

posted @ 2022-02-28 17:21  滴哒哒哒  阅读(258)  评论(0编辑  收藏  举报