Zhonghui

每个不曾起舞的日子,都是对生命的辜负

User Tools

Site Tools


程序:cpp:左值和右值

C++左值和右值

C/C++ 关于左值(lvalue)和右值(rvalue)的定义,似乎有一些历史遗留问题,我们这里只讨论C++ 11之后的内容

参考资料:

  1. [C++] 深入了解左值与右值 https://nihil.cc/posts/cpp_lvalue_rvalue/
  2. C++中的左值和右值 gutsgwh1997.github.io
  3. C++中的左值与右值 Github

区别

C++中所有的值都必然属于左值、右值二者之一。左值是指表达式结束后依然存在的持久化对象,右值是指表达式结束时就不再存在的临时对象。所有的具名变量或者对象都是左值,而右值不具名。很难得到左值和右值的真正定义,但是有一个可以区分左值和右值的便捷方法:看能不能对表达式取地址,如果能,则为左值,否则为右值。左值一般在内存中,右值一般在内存或CPU寄存器中。

区分什么是左值和右值
左值 (lvalue, locator value) 表示了一个占据内存中某个可识别的位置(也就是一个地址)的对象。
左值包括:可修改的左值和不可修改的左值(数组类型的左值、不完整类型的左值或者具有 const 限定的左值)。
右值 (rvalue) 则使用排除法来定义。一个表达式不是【左值】就是【右值】。 那么,右值是一个【不表示】内存中某个可识别位置的对象的表达式。
L → R: 除了数组、函数、不完整类型的所有左值都可以转换为右值。
R → L: 那右值能否转换为左值呢?当然不能!根据左值的定义,这违反了左值的本质。不过,右值可以通过一些更显式的方法产生左值。例如,一元解引用操作符 '*' 需要一个右值参数,但返回一个左值结果。

CV限定

CV 限定符 这个术语指的是 const 和 volatile 两个类型限定符。每个类型都有三个对应的 CV-限定类型版本: const 限定 、 volatile 限定 和 const-volatile 限定 版本。有或无 CV 限定的不同版本的类型是不同的类型,但写法和赋值需求都是相同的。

亡值

引用和指针

& 表示左值引用(也就是普通的引用),因此,不能将一个右值赋值给(非常量的)左值引用。常量的 左值引用可以使用右值赋值。因为你无法通过常量的引用修改变量的值,也就不会出现修改了右值的情况。这也使得 C++ 中一个常见的习惯成为可能:函数的参数使用常量引用接收参数,避免创建不必要的临时对象。
纯右值可以绑定到 const 限定的左值引用

右值引用:参见之前写的资料(左值和右值的主要区别是,左值可以被修改,而右值不能。不过,C++11 改变了这一区别。在一些特殊的情况下,我们可以使用右值的引用,并对右值进行修改。)
和拷贝构造函数Foo(Foo&)不一样的是,搬移构造函数接受的是一个右值引用:Foo(Foo&&)。如果是从一个临时变量来构造新的`Foo`的话,编译器会优先调用搬移构造函数,来把临时对象开膛破肚,取出自己需要的东西。拷贝构造函数就不敢这么做,因为它不确定对象在其他地方有没有被使用,如果误操作了,恐怕会被人打。

左值引用和右值引用

左值引用就是普通的引用,右值引用见这里右值引用

int x = 0;
int &rx = x; // 普通引用,也就是左值引用

移动

C++11提供了std::move来废弃一个对象,也就是把它标识为临时变量,这样可以丢给搬移构造函数处理

/var/www/DokuWikiStick/dokuwiki/data/pages/程序/cpp/左值和右值.txt · Last modified: 2025/05/18 13:49 by zhonghui