C语言中左值右值概念如何区分?

摘要:一、什么是左值右值 很多人称左值是有地址的值(located value), 不完全正确。 左值是有某种存储支持的变量,右值是临时值。 左值引用仅仅接受左值,除非是用const; 右值引用仅仅支持右值, 随着这个系列的深入,特别是移动语义的
一、什么是左值右值 很多人称左值是有地址的值(located value), 不完全正确。 左值是有某种存储支持的变量,右值是临时值。 左值引用仅仅接受左值,除非是用const; 右值引用仅仅支持右值, 随着这个系列的深入,特别是移动语义的情况,我们会越来越清楚地知道,为什么它很重要了。 #include<iostream> #include<string> int GetValue() { return 10; } int& GetValueRef() { static int value = 10; return value; } void SetValue(int value) { } //只支持接收左值参数 (非常量,可modify) void SetValueRefOnlyLeftValue(int& value) { } //同时持接收左值和右值两种参数,(常量,不可modify) void SetValueRefBothLeftRightValue(const int& value) { } void testLeftRightValue01() { int i = 10; //错误 '=': left operand must be l-value //10 = i; int a = i; //右值也可以是一个带返回值的函数,是临时的值,没有位置,没有存储空间,只是返回一个值 int k = GetValue(); //❌️ '=': left operand must be l-value //GetValue() = i; //编译可以通过,左值引用 GetValueRef() = 5; SetValue(i); SetValue(10); SetValueRefOnlyLeftValue(i); //'void SetValueRefOnlyLeftValue(int &)': cannot convert argument 1 from 'int' to 'int &' //SetValueRefOnlyLeftValue(10); //不能将右值赋给左值引用,所以左值引用的,只能是左值 //'initializing': cannot convert from 'int' to 'int &' //int& b = 10; //但是左值引用如果加上了const的话,则可以 const int& c = 20; //这是一个特殊规则,它是一种变通方法,实际情况是,编译器可能会用你的存储创建一个临时变量,然后把它赋值给那个引用 //所以,实际上它不可避免的创建了一个左值,但也同时支持了左值和右值: int temp = 10; const int& cc = temp; } //Only support left value void PrintNameLeftValue(std::string& name) { std::cout << "[lvalue] " << name << std::endl; } //Support both left and righ value void PrintNameBothValue(const std::string& name) { std::cout << "[lrvalue] " << name << std::endl; } //有了右值引用,我们现在有了一种方法来检测临时值,并对它们做一些特殊的事情(通过方法的重载,可以将leftValue(), BothValue(), RightValue() 方法同名重载,) //这非常有用,尤其是在移动语义上 //如果我们传入的事一个临时对象,我们就不需要关心它们是否活着,是否完整,是否拷贝。我们可以轻松的触及它的资源,给到特定的对象,或者其它地方使用它们,因为我们知道它是暂时的,它不会存在很长时间。
阅读全文