转自http://www.cnblogs.com/areliang/archive/2011/11/16/2251480.html
今天看C++模板的资料,里面说到lvalue,rvalue的问题,这个问题以前也看到过,也查过相关资料,但是没有考虑得很深,只知道rvalue不能取地址,不能赋值等等一些规则。今天则突然有了更深层次的理解(也可以说是顿悟,耗时不过几秒钟),记录下来。
下面是我对这两个单词字面的意思的猜测:
- lvalue估计来源于left value。 在赋值语句中lvalue = rvalue;位置处于左边。就是可以修改的值。
- rvalue估计来源于right value。处于赋值语句右边,是只读的不可修改的值。
接下来是我所悟到内容的详细分析
-
lvalue(左值)是可以赋值的,说明它是一个变量,它在内存中一定存在,一定有地址。所以&lvalue是有效的,能取到在内存中的地址。
访问lvalue一定会导致CPU访问存储器(相对较慢的操作)。
lvalue的例子:
- int a;
- a = 10; // a是lvalue。
- int* p = &a; // &a是rvalue。
- &a = 0; //错误,&a不是lvalue,因为a的地址一旦分配好了,就不能改变了。
-
rvalue是不可以赋值的,它不是一个变量,在内存中没有存在,没有地址。它要么是存在于CPU的寄存器中,要么是存在于指令中(立即数)。所以只要对rvalue取地址,那么就一定是错误的(编译器会抱怨的)。
访问rvalue不会导致CPU访问存储器(对立即数和寄存器的访问很快)。
rvalue的例子:
- int a;
- a = 10; // 10是rvalue,它没有地址,&10就是错误的表达式。从汇编语言的角度来看,10是直接存在于MOV指令中的立即数。
- 10 = a; // 错误,10是rvalue,不可赋值。
- //函数返回值属于rvalue,因为返回值通常用CPU寄存器传递,没有地址。
- int foo()
- {
- return 0;
- }
- int b = foo(); //没问题,函数返回值是rvalue。
- int* p = &foo(); //错误,rvalue没有地址。
- void bar(int& i) // 右值是临时对象,是const类型,不能将非const 类型对象绑定到const对象上
- //反之可以,可以将const对象绑定到非const对象上
- {
- }
- bar(foo()); //错误,bar函数参数需要的是lvalue。
- 函数的返回值是rvalue,对于返回int, char 等这样最基本的类型,是通过CPU寄存器返回的,因此返回值没有地址是可以理解的。但是如果函数返回的是一个用户自定义类型的对象,肯定不可能通过寄存器来返回这个对象值的(寄存器大小数量都有限,对象的大小可以非常大),那究竟是怎样返回对象的呢?
- class UDT
- {
- int data[100];
- public:
- UDT()
- {
- printf("construct/n");
- }
- BBB& operator = (BBB& )
- {
- printf("operator =/n");
- return *this;
- }
- };
- UDT foo()
- {
- return UDT();
- }
- void main()
- {
- UDT obj = foo();
- }
- //输出:
- construct
带着疑问,我查了查vc编译出来的代码,原来obj这个局部变量的地址被压入了堆栈,foo函数内部以堆栈上的obj地址作为this指针调用了UDT的构造函数。噢,难怪执行UDT obj = foo();这个语句只有调用了一次构造函数,而没有调用operator =,这都是因为函数返回值必须是rvalue这个规则所带来的好处,如果返回值是一个lvalue(左值),那么这个语句一定会调用operator = 运算符。
相关推荐
其中,第6.10小节(Lvalues and rvalues)和第7.15小节(Expressions)等特定部分着重介绍了C++的左值和右值,以及表达式的使用方法。整个文档是一份深度的技术资料,对于程序员而言,它是理解和应用C++17标准的关键...
C++中的值类别也是基础知识点之一,“Lvalues and Rvalues (Visual C++)”部分讲解了左值和右值的概念,以及它们如何影响赋值和函数调用。此外,“Temporary Objects”章节则详细说明了临时对象的生命周期及其在代码...
类型系统(Types)、左值和右值(Lvalues and rvalues)在C++11中也是不可或缺的知识点。类型系统定义了数据在C++中的表达方式,包括基本类型(如整型、浮点型)和复合类型(如数组、结构体、类)。而左值和右值的...
- **左值和右值 (Lvalues and rvalues)**:解释了左值和右值的区别及其使用场景。 - **对齐 (Alignment)**:说明了数据在内存中的对齐方式。 4. **标准转换 (Standard conversions)** - **左值到右值转换 ...
- **3.10 Lvalues and rvalues**:解释了左值和右值的概念及其在C++中的应用。 - **3.11 Alignment**:定义了对齐的要求,确保数据结构的高效访问。 #### 标准转换 - **4.1 Lvalue-to-rvalue conversion**:描述了...
- **Lvalues and rvalues (左值与右值)**:区分了可以出现在赋值操作左侧的对象(左值)和不能出现在左侧的对象(右值)。 #### 结论 2011 C++ ISO标准(第三版)是C++语言的一个重要里程碑,它不仅定义了语言的...
- **左值与右值**(Lvalues and rvalues) - **对齐**(Alignment) ##### 4. 标准转换 (Standard conversions) 这部分介绍了C++中的各种类型转换规则,如: - **左值转右值转换**(Lvalue-to-rvalue conversion)...
- **3.10 Lvalues and rvalues**:左值和右值的区别。 - **3.11 Alignment**:对齐要求的说明。 #### 4. Standard conversions(标准转换) - **4.1 Lvalue-to-rvalue conversion**:左值到右值的转换。 - **4.2 ...
- **左值和右值(Lvalues and Rvalues)**:左值是可以出现在赋值语句左边的表达式,而右值则只能出现在右边。 - **类型转换(Type Conversions)**:在不同类型之间进行自动或显式转换。 - **常量表达式(Constant ...
10. **Lvalues and rvalues**:区分了左值和右值的概念。 11. **Alignment**:规定了对齐的要求。 #### 六、Standard conversions 部分 1. **Lvalue-to-rvalue conversion**:介绍了一种转换类型。 2. **Array-to-...
- **3.10 左值和右值 (Lvalues and rvalues)**:区分了左值和右值的概念。 - **3.11 对齐 (Alignment)**:规定了数据成员在内存中的对齐方式。 4. **标准转换 (Standard conversions)** - **4.1 左值到右值的...
- lvalues和rvalues(Lvalues and rvalues)区分了可左值引用和可右值引用的对象。 - 对齐(Alignment)讨论了如何控制对象在内存中的对齐方式。 4. 标准转换(Standard conversions) - 本节讲解了C++中的隐式...
- **Lvalues and rvalues**(左值与右值):区分了左值和右值的区别及其使用场景。 - **Alignment**(对齐):定义了对象在内存中的对齐方式。 ##### 4. Standard conversions(标准转换) - **Lvalue-to-rvalue ...
- **3.10 Lvalues and rvalues 左值和右值**:区分了左值和右值,并介绍了它们的应用场景。 - **3.11 Alignment 对齐**:讨论了内存对齐的要求及其对性能的影响。 - **4. Standard conversions 标准转换** - **...
##### Lvalues and Rvalues in C - **Lvalue:** An expression that refers to a memory location and can appear on the left-hand side of an assignment. - **Rvalue:** An expression representing a value ...
#### 一、L值与R值 (Lvalues and Rvalues) 在C++中,“L值”与“R值”的概念对于理解变量、表达式以及赋值操作至关重要。 - **定义**:在赋值语句`v = e;`中,左侧(`v`)必须能表示一个内存地址,以便存储右侧(`...