左值(Lvalues)与右值(Rvalues)

左值(Lvalues)与右值(Rvalues),第1张

左值(Lvalues)与右值(Rvalues) 左值(Lvalues)与右值(Rvalues) 定义

Every C++ expression has a type, and belongs to a value category.

左值右值都是表达式属性,该属性称为value category.

在现代C++中,对于左值表达式,通过具体名字和引用来指定一个对象,非左值就是右值。

左值表示程序中必须有一个特定的名字引用到这个值。

An lvalue has an address that your program can access. Examples of lvalue expressions include variable names, including const variables, array elements, function calls that return an lvalue reference, bit-fields, unions, and class members.

右值表示程序中没有一个特定的名字引用到这个值。

区分

区分表达式的左右值属性一个简便方法:若可对表达式用 & 符取址,则为左值,否则为右值。

举例:

&obj,&*ptr,&ptr[index],&++x有效&1729,&(x+y),&std::string(“meow”),&x++无效
int x = 0;
++x;   // lvalue
x++;   // rvalue

++x修改自身值,并返回自身;x++先创建一个临时变量,为其赋值,而后修改x的值,最后返回临时对象。

int x = 0;
++++x;  // ok
x++++;  // 报错

前++是直接对对象自增后返回对象,而后++会先返回记录当前值,再自增,最后返回一个无名的临时对象,那么x++++就是让第一个后++返回的无名临时对象再自增,这样对C++是无意义的,所以这样就无法编译通过。

引用

Type& :只能绑定到可修改的左值表达式

const Type& : 可以绑定到任何表达式

Type&&:可绑定到可修改的左值或右值表达式

const Type&&:可绑定到任何表达式

Error:non-const lvalue reference cannot bind to a temporary
void swap(int& a, int& b) {
    // ...
}

int main() {
    int a = 10;
    int b = 5;
    swap(a + 1, b + a);
}

执行上述代码会报如下错误:

Error : non-const lvalue reference to type 'int' cannot bind to a temporary of type 'int'

调用swap函数时,a+1和a+b的值会存在一个临时变量中,当把这两个临时变量传递给swap时,由于swap的参数是int &,不是常量引用,因此会产生编译错误。

错误原因:

变量a在内存中有确切的地址,变量b在内存中也有确切的地址,但是a+b却没有,a+b不是左值(a+1也不是),只是临时计算一下,然后将得出的结果用于其他语句,之后空间就被释放了,如果绑定一个非const引用到a+b相当于一个野指针(引用的本质是一个指针常量),所以是不允许的。

临时变量不能作为非const引用参数,是C++编译器的一个关于语义的限制。如果一个参数是以非const引用传入,C++编译器就有理由认为程序员会在函数中修改这个值,并且这个被修改的引用在函数返回后要发挥作用。但如果把一个临时变量当作非const引用参数传进来,由于临时变量的特殊性,程序员并不能 *** 作临时变量,而且临时变量随时可能被释放掉,所以,一般说来,修改一个临时变量是毫无意义的,据此,C++编译器加入了临时变量不能作为非const引用的这个语义限制,意在限制这个非常规用法的潜在错误。

解决方案:

void swap(const int& a, const int& b) {
    // ...
}

int main() {
    int a = 10;
    int b = 5;
    swap(a + 1, b + a);
}

将普通引用改为常量引用,改为常量引用后不能修改绑定的对象,只能读不能写。

assigning a temporary object to the const reference extends the lifetime of this object to the lifetime of the const reference

为什么此方案可行?因为常量引用会延长临时变量的生命周期!

Reference

Lvalues and Rvalues(C++)左值(lvalues)和右值(rvalues)表达式左值右值(C++学习)C++沉思录:x+y不是左值,不能绑定一个非const引用到自身C++中临时变量不能作为非const的引用参数的方法C++ non-const lvalue reference cannot bind to a temporaryC++之error: cannot bind non-const lvalue reference of type ‘myString&’ to an rvalue of type ‘myString’

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5713666.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存