对于左值和右值还有一些模糊的地方:
书上说左值(L-value)是指地址值,右值(R-value)是指数据值。
但对于***右值指的是引用了一个存储在某个内存地址里的数据***这句话不是特别清楚,比如说:a = 5,
1、数值5是来自于内存中的某个特定存储区域吗,而且无论数值大小均是这么来的吗(记忆中好像不是的呢)?
2、使用数值5的时候是以copy的方式还是其他的方式得到的?
3、或者是在赋值之前临时创建的大小为int的空间来存储5,并非是从内存中的引用?
4、关于这方面有什么相关的书籍推荐么?
先谢谢各位不吝赐教。
PHP中文网2017-04-17 13:29:56
C语言不是很精通,但是还是在此说一下自己的理解,如有不正确请指出。
个人觉得,“右值”不应该仅仅是指内存地址中的数据。比如a = 5
, 5
就是一个直接数而非内存地址,正如汇编中可以直接往寄存器中写直接数,也可以写内存地址中的数一样。因为对这种直接数取地址的话是没有意义的。
我只知道java
中的String
在直接赋值为字符串时,该字符串是共享常量池中的字符串的,但是C语言中不知道有没有类似的机制。对于a = 5
这种赋值来说应该和直接的立即数写入差不多;而对于int a;int b = 5; a = b;
这种赋值来说应该是拷贝无疑。这时b
就是“引用了某个内存地址里的数据”。
个人觉得对于这种简单赋值来说临时创建空间存储然后拷贝过去在实现上看应该没有必要(没有求证过)。
平常不用C,而且本人学习不深,无法给出有价值的推荐。
以上都是个人见解,没有求证过,供题主参考。如有错误还请指出。
大家讲道理2017-04-17 13:29:56
不晓得你看的什么书,我不大明白这个地址值和数据值的定义
一个左值可能是一个函数或者对象。
一个右值可能是一个对象、临时对象或者临时对象的子对象、或者不是对象的值
具体可以参阅标准3.10小节,讲的就是左值与右值
至于5所在的内存位置,对于这种整数来说,对于编译器来讲一般都是使用立即数直接赋值,5并没有临时存在于什么地方,
就像是把5放在a所在的栈上的位置,那么这句话就是 a = 5;
如果是字符串,有可能存储在其他位置比如代码段,然后拷贝过来,这样就是 str = "123143";
怪我咯2017-04-17 13:29:56
其他的我不是很懂
但是:
左值和右值都是针对表达式而言的,左值是指表达式结束后依然存在的持久对象,右值是指表达式结束时就不再存在的临时对象。
一个区分左值与右值的便捷方法是:看能不能对表达式取地址,如果能,则为左值,否则为右值
阿神2017-04-17 13:29:56
不太清楚题主问的是 C 还是 C++,如果是 C++ 的话,是哪一版标准的 C++。我这里只说 C++11 中关于左值和右值的问题。
粗略的来讲,当一个对象被用作右值(rvalue)的时候,使用的是这个对象的值(它的内容);当一个对象被用作左值(lvalue)的时候,使用的是这个对象的身份(它在内存中的位置)。
对于表达式a = 5;
,假设a
为int
类型。其中等号左边的表达式a
的类型是左值,因为我们需要用到它的身份(它在内存中的位置),才能把值赋给它。等号右边的表达式5
的类型是右值,因为我们需要用到它的值(它的内容)。
1、数值
5
是来自于内存中的某个特定存储区域吗,而且无论数值大小均是这么来的吗(记忆中好像不是的呢)?
数值5
是 一个 literal,它的类型是右值(更准确的说是 prvalue,见下文),应该是保存在静态内存(static memory)中。无论大小,只要是 literal 都如此,例如 2333333333333333ULL
。
2、使用数值
5
的时候是以copy的方式还是其他的方式得到的?
在表达式a = 5;
中,应该是内置赋值运算符将5从静态内存复制到变量a
中。
对于自定义的赋值运算符,就要看:1. 是否定义了拷贝赋值运算符(copy-assignment operator)和移动赋值运算符(move-assignment operator),2. 等号右侧表达式的值类型,从而确定是拷贝还是移动。
3、或者是在赋值之前临时创建的大小为int的空间来存储5,并非是从内存中的引用?
不是。
4、关于这方面有什么相关的书籍推荐么?
不清楚有没有专门论述这方面的书籍,不过你可以看看本文末尾参考部分的文档和 C++11 标准。
以下为引申内容。
C++ 中的表达式(expression,例如操作符和它的操作数、变量名等)是根据两个方面进行分类的:类型和值类别。每个表达式都必定属于三个主要值类别(见下文)之一。
在 C++11 之前,表达式的值类别分为左值(lvalue)和右值(rvalue)两种,而自 C++11 起,表达式的值类别分为 lvalue、xvalue、prvalue、glvalue、rvalue 五种。之所以引入了这么多种值类型,是因为 C++11 中新增的移动语义(move semantics)。
他们之间的关系如下图所示:
expression
|
+------+-------+
| |
v v
glvalue rvalue <-- 混合值类别(mixed value categories)
| |
+-----+-----+ +-----+-----+
| | | |
v v v v
lvalue xvalue prvalue <-- 主要值类别(primary value categories)
表达式的值类别分类的标准是两点:
有无身份(has identity) 即是否能通过比较两个表达式的身份判断他们是否是同一个表达式。
能否被移走(can be moved from) 即能把表达式的值移到其它变量中去,使原变量处于一种不确定但有效的状态(例如能正常析构)。
这5个值类别之间的关系如下表所示:
| value | has identity | can be moved from |
+============+==============+===================+
| lvalue | yes | no |
| xvalue | yes | yes |
| prvalue | no | yes |
| (not used) | no | no |
+------------+--------------+-------------------+
| glvalue | yes | ? | pre-C++11 lvalue
| rvalue | ? | yes | pre-C++11 rvalue
From C++11 standard § 3.10
— An lvalue (so called, historically, because lvalues could appear on the left-hand side of an assignment expression) designates a function or an object. [ Example: If E is an expression of pointer type, then *E is an lvalue expression referring to the object or function to which E points. As another example, the result of calling a function whose return type is an lvalue reference is an lvalue. —end example ]
— An xvalue (an “eXpiring” value) also refers to an object, usually near the end of its lifetime (so that its resources may be moved, for example). An xvalue is the result of certain kinds of expressions involving rvalue references (8.3.2). [ Example: The result of calling a function whose return type is an rvalue reference is an xvalue. —end example ]
— A glvalue (“generalized” lvalue) is an lvalue or an xvalue.
— An rvalue (so called, historically, because rvalues could appear on the right-hand side of an assignment expression) is an xvalue, a temporary object (12.2) or subobject thereof, or a value that is not associated with an object.
— A prvalue (“pure” rvalue) is an rvalue that is not an xvalue. [ Example: The result of calling a function whose return type is not a reference is a prvalue. The value of a literal such as 12, 7.3e5, or true is also a prvalue. —end example ]
C++ 中表达式的值的类别:Value categories
C++ 中值分类名称的变化由来:“New” Value Terminology
C++0x 到 C++11 值分类名称的变化:n3055