c++中左值和右值是什么意思_左值和右值

        封面图片由 "wu_wythe​​​​​​" 黑色油墨 原创并友情赞助,特此感谢。

C++引进右值的概念,是为了明确临时变量的类型,在此基础减少反复调用构造函数和析构函数带来的性能损失。

区分左值、右值的意义

没有右值概念时,临时变量的值属性是十分模糊的,它可以被 const type&引用,但它本身并不是常量,比如临时变量可以调用成员函数改变自己。有了右值概念后,临时变量才明确了值属性:右值。

如何区分

左值:具名变量,能取地址

右值:匿名变量,不能取地址

特例:

字符串字面值(string literal)属于特殊情况,匿名变量,但可以取地址,属于const char []类型 其他字面值常量属于右值(注意不是右值常量 !)

表达式属性

c++表达式有两个属性:类型(type)和 值属性(value category)。

左值引用和右值引用属于类型 左值和右值属于值属性

int k = 5;//k类型:int,值属性:左值int& j = 5; //j类型:int&,值属性:左值int&& i = 5; //i类型:int&&,值属性:左值

上述三个表达式,除了类型不同外,在后续代码中使用并没有别的差别

decltype(k); //intdecltype(j) ;//int&decltype(i) ;// int&&

你可能会奇怪,我为什么需要这么麻烦的表达,直接用k这样的传值方式不好么,这一切都是为了万恶的效率。

这对普通人来说,效率根本不重要,我们只需要是要了解它即可。函数参数(parameter)的值属性可以区分实参(argument)的类型,从而针对左右值分别编写构造赋值函数,提升程序效率。

// void fun(int parameter);//编译器不允许它与下面两个函数共存void fun(int& parameter); //实参类型为左值时,调用它void fun(int&& parameter);//实参类型为右值时,调用它
fun(j);//调用左值引用版本,如果不存在左值版本,会出错fun(5);//调用右值引用版本,如果不存在右值版本,会出错

请注意如下调用,全部匹配void fun(int& parameter)

fun(k);//arugment(实参)是左值fun(j);//arugment(实参)是左值fun(i);//arugment(实参)是左值

如何判断表达式的左右值属性

所有的值必属于左值、将亡值、纯右值三者之一。

纯右值:函数by value返回的局部变量 运算表达式产生的临时变量 原始字面量(string literal除外)和lambda。

将亡值:强制转换为Type&& 右值对象的成员变量

在函数argument——parameter匹配时,将亡值和纯右值都看做右值。

如何匹配

我们注意到f(j)和f(5)的调用,如果不存在对于函数版本,他们的调用就会出错。(为什么你写的程序不会出错,因为你使用的是void fun(int parameter))

函数形参可接受的实参值属性

parameter’s

type

argument’s

value category

Type& lval左值
const Type&clval,val,crval,rval全部类型
Type&&rval  右值
const Type&&crval,rval右值和右值常量

注意Type是指某个具体类型,不是函数模板类型参数。

右值常量实参匹配到右值常量引用版本的函数,如果不存在此版本,则匹配到左值常引用的函数版本。右值实参的匹配顺序为Type&&→const Type&&→const Type&&。

右值引用是指 他所引用的变量是右值,(右值二字)限定的是别人,而右值引用自身是左值;const引用限定的是自己修改对象的能力,它出现在接口中只是为了扩大函数可接受的参数范围。

上述例子中的整数“5”是右值,而非右值常量。


后面讲陆续总结模板推导和函数返回值优化,move与完美转发。欢迎大家私信探讨。

--

参考资料

[1] Effective Modern C++ [2] 左值和右值https://blog.csdn.net/linuxheik/article/details/78929128

25ae829d993f9e938e791f8b8bb169dd.png

表情包
插入表情
评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符
相关推荐
©️2020 CSDN 皮肤主题: 游动-白 设计师:白松林 返回首页