贵州交通建设集团网站,中国网站用Cn域名,网络项目网,丑陋网站设计赏析左值和右值好干嘛#xff1f;
深入理解左值和右值可以帮助我们对代码进行优化
一、什么是左值和右值
左值#xff1a;有某种存储支持的变量 右值#xff1a;临时值#xff08;字面量、函数的结果#xff09;
Ⅰ右值是字面量
int yy 22;22本身就是一个临时的#xf…左值和右值好干嘛
深入理解左值和右值可以帮助我们对代码进行优化
一、什么是左值和右值
左值有某种存储支持的变量 右值临时值字面量、函数的结果
Ⅰ右值是字面量
int yy 22;22本身就是一个临时的系统不会存储它故22是右值 而yy是一个int型变量系统会为其开辟一个int大小的内存空间故yy是左值
这下就应该很容易理解了吧
右值可以赋值给左值左值不可以赋值给右值
int yy 99;//右值99可以赋值给左值yy
10 yy;//左值yy不可以赋值给右值10其本质是因为左值是有地址的有存储空间而右值没有是一个临时值而已存活时间不长
这时候就可以优化代码了我们不需要过于关注右值因为它活不长这就涉及到优化的问题了
可以证明字面量是个右值
Ⅱ右值是函数的结果
①函数无参数
beyond是一个返回一个int的函数其是一个右值
int year beyond();year是左值函数的结果是个右值右值可以赋值给左值正确 beyond() year;报错因为beyond()是右值而year是左值左值不可以赋值给右值
int beyond()
{return 1993;
}int main()
{int year beyond();beyond() year;//error表达式必须是可修改的左值return 0;
}可以证明函数的结果是右值
②函数有参数
函数beyond接收的参数为左值因为year是一个int型有存储地址
beyond(1993);若调用函数beyond传入右值也是可以的 这种情况当函数被调用时会自动通过该右值1993来创建一个左值例如int temp 1993; beyond(temp);
int beyond(int year)
{return year;
}int main()
{int year 1993;beyond(year);beyond(1993);//1993为临时变量右值它会被系统自动转为一个左值使用return 0;
}二、左值引用
Ⅰ函数返回类型为左值引用
函数beyond返回值为左值引用int也就是return year;这个左值的引用 这下子函数的结果就变成了左值其值就是左值year int year beyond();左值引用beyond可以赋值给左值 beyond() 1999;因为beyond()时左值故可以将右值1999赋值给左值beyond()
#include iostreamint beyond()
{int year 1993;std::cout beyond_year: year std::endl;return year;
}int main()
{int year beyond();//√beyond() 1999;//√return 0;
}Ⅱ函数参数为左值引用
函数beyond的参数为左值引用int yearint year是个左值取它的引用
void beyond(int year){}int main()
{int year 1993;beyond(year);//√beyond(1993);//× 非常量引用的初始值必须为左值return 0;
}可以看到函数参数为左值引用若传入一个右值会报错 变通方法加上const即可 这也是很多项目里面函数参数常使用const的原因之一因为函数参数可以传入左值和右值
const int year加上const就可以了既可以传入左值也可以传入右值
void beyond(const int year){}int main()
{int year 1993;beyond(year);//√beyond(1993);//√return 0;
}const左值引用的本质
右值10是不可以赋值给左值引用int a的
int a 10;//×若加上const就可以了因为有编译器默默的进行了转换将右值10转换为一个临时变量temp然后把这个临时变量赋值给左值
const int a 10;//√//等价于
int temp 10;
int a temp;const int可以接收左值和右值建议使用
Ⅲ如何判断是左值还是右值
写个函数函数的参数是左值引用即可因为右值的话传不进来 vocal、guitarist 、band 是左值 Huangjiaju、Huangguanzhong和vocal guitarist是右值 其中vocal guitarist组成了一个临时字符串然后赋值给左值band 临时值也就是右值没有地址
#include iostreamvoid beyond(std::string name)
{std::cout name std::endl;
}int main()
{std::string vocal Huangjiaju;std::string guitarist Huangguanzhong;std::string band vocal guitarist;beyond(vocal);beyond(guitarist);beyond(band);beyond(vocal guitarist);//×return 0;
}常量引用如const int能兼容临时的右值和实际存在的左值变量
三、右值引用
左值引用例如const int接收左值类似的右值引用接收右值临时对象
右值引用例如const int相对于左值引用多了一个
将函数beyond的参数改为右值引用std::string name报错的就是传入左值了
#include iostreamvoid beyond(std::string name)
{std::cout name std::endl;
}int main()
{std::string vocal Huangjiaju;std::string guitarist Huangguanzhong;std::string band vocal guitarist;beyond(vocal);//×beyond(guitarist);//×beyond(band);//×beyond(vocal guitarist);//√return 0;
}此时肯定会有同学发现若要进行函数重载一个是const左值引用另一个是右值引用会咋样 const 左值引用支持左值和右值const std::string name 右值引用只能传入右值std::string name
#include iostreamvoid beyond(const std::string name)
{std::cout const 左值引用 name std::endl;
}void beyond(std::string name)
{std::cout 右值引用 name std::endl;
}int main()
{std::string vocal Huangjiaju;std::string guitarist Huangguanzhong;std::string band vocal guitarist;beyond(vocal);//√beyond(guitarist);//√beyond(band);//√beyond(vocal guitarist);//√return 0;
}贴下结果 分析可以看到beyond(vocal guitarist);调用的是右值引用的函数 vocal guitarist是右值std::string name只能接收右值const std::string name既可以接收左值也可以接收右值 编译器最终选择了std::string name 这种设计的主要目的是允许开发者提供特定于右值的优化如移动语义从而提高代码的性能
四、小结
左值是有实际内存空间的右值是临时值 左值引用只接受左值右值引用只接受右值 左值引用加上const既可以接收左值也可以接收右值
会不会有同学问为啥没有右值引用加const呢 是不是小傻蛋右值就是一个临时值很快就会消失的哪来的const修饰
看了很多博客解释各有差异也有很多坑 这是我理解透之后总结出来的感谢网上的很多博主的博客看了很多这里就不一一列举了
如果该篇博文对您产生了一丢丢的帮助还请各位观众老爷给个赞谢谢~~