RValue 由啥构成?
Posted
技术标签:
【中文标题】RValue 由啥构成?【英文标题】:What constitutes of RValues?RValue 由什么构成? 【发布时间】:2011-12-21 06:34:11 【问题描述】:RValues 是不可操作的内存区域,所以像整数这样的字面量被认为是 RValues。
-
常量是否构成 RValues?
const int x = 0;
至少可操作一次。
现在,编译器创建的临时对象也是 RValue,即使它们具有可操作的内存区域。为什么会这样?
因为它们不能被“用户”修改?是这个原因吗?
那么,“用户”无法操作的内存区域称为 RValue?
【问题讨论】:
【参考方案1】:标量右值是计算为标量值的表达式,如 42
或 i + k
(而标量左值是计算为标量对象的表达式,如 i
或 *int_ptr
或 numbers[0]
)。
类类型的右值是计算为临时对象的表达式。最突出的例子是调用按值返回类对象的函数:
std::string foo()
return "hello world";
鉴于上述函数定义,表达式foo()
是一个右值。请注意,我说的不是 result(它是一个临时对象),而是 expression foo()
,其评估会产生该结果。
【讨论】:
你应该强调“价值”和“对象”:-)【参考方案2】:常量是否构成 RValues?常量 int x = 0;可操作于 至少一次。
在您的声明中,x
既不是右值也不是左值,它被称为 declarator-id。 (参见 C++03 中 8/4 的语法)当它用于(子)表达式时,它是一个不可修改的左值,可以初始化为任何常量表达式。
2.现在,编译器创建的临时对象也是 RValues,即使它们具有可操作的内存区域。为什么呢? 因为它们不能被“用户”修改?是这个原因吗?
类类型的右值可以是可修改的或不可修改的,但内置类型的右值始终是 cv-unqualified。
§ 3.10/9 类右值可以有 cv 限定类型;非类右值 总是有 cv 不合格的类型。
考虑这个例子:
struct S
int x;
void f(int s) x = s;
;
// ill-formed: Cannot assign to an rvalue of built-in type.
S().x = 42;
// Valid: A member function can be used to modify the referent of rvalue.
S().f(42);
子表达式S()
创建一个类类型的右值,其生命周期是结束; 全表达式。
【讨论】:
LValue 究竟由什么组成? "S().x
" 嗯...不清楚这是否真的应该是右值:给S
添加一个空的默认ctor,然后告诉我S().x
的值是多少?
@AnishaKaul "LValues 究竟由什么组成?" C++ 标准所说的左值;对于每个 C++ 表达式,查找 C++ 标准中的定义以了解它是否为左值。
@curiousguy:不,不会有任何区别,因为S().x
是一个指向临时对象的右值表达式。
@AnishaKaul 不,对于每个可能的 C++ 表达式,查找此类表达式的定义,它会说明它是左值还是右值。【参考方案3】:
lvalue
指的是内存位置,我们可以使用 &
运算符获取该内存位置的地址。 rvalue
是不是lvalue
的表达式。
1. Do constants constitute RValues? const int x = 0; is maniputable at least one time.
不,因为你这样做 - const int *p = &x
【讨论】:
"我们可以使用 & 运算符获取该内存位置的地址" 并非总是如此。 @curiousguy:你能举个反例吗?【参考方案4】:所有变量,包括不可修改 (const) 变量,都是左值。所以 x 是左值,而 0 是右值。
临时对象被设为右值,因为它们不存在于该特定语句之外。
您可以阅读更多here
【讨论】:
临时对象有时会持续整个块(甚至直到程序终止)。【参考方案5】:RValues 是不可操作的内存区域
右值是表达式,而不是“事物”。
右值可以引用对象(“内存的可操作区域”)。
所以像整数这样的字面量被认为是 RValues。
文字是右值(不是“考虑”的右值)因为 C++ 是这样定义的。
常量是否构成 RValues?
const int x = 0;
其实x
是一个const int
类型的变量。
鉴于x
的上述定义,表达式x
是一个左值。
现在,编译器创建的临时对象也是 RValues
不,右值是表达式,不是对象。
即使它们有可操作的内存区域。为什么会这样?
事实并非如此。
因为它们不能被“用户”修改?是这个原因吗?
右值是右值,因为语言是这样定义的。
那么,“用户”无法操作的内存区域称为 RValue?
不,右值只指定表达式,而不是内存等运行时存在的东西。
右值有时可以引用一个对象,这是一个用户可以操作的“内存区域”。
“用户”无法操作的内存区域
不清楚你在这里的意思;你的意思是只读存储器,还是别的什么?
【讨论】:
【参考方案6】:首先 - lval 和 rval 是表达式的属性 - 表达式要么是 rval 要么是 lval。
要回答您的其他问题,由 rvals 创建的 临时对象 可以通过 rval 引用进行修改 - 此功能是在 c++11 中添加的
此功能对于 1) 应用移动语义 2) 完美转发非常有用。
在http://blogs.msdn.com/b/vcblog/archive/2009/02/03/rvalue-references-c-0x-features-in-vc10-part-2.aspx了解更多信息
【讨论】:
"如果你能用'&'得到表达式结果的地址——那么这意味着表达式是一个lval。如果不是,那么它就是一个rval。 i>”这不是真的。&lvalue
有效而&rvalue
无效是经常,但并非总是。 (如果简单地定义了 l/r 值......)反驳也不是新的:在 C/C++ 中,结构成员可以是位字段int i:2; // 2 bits value
;当命名时,这个成员确实是一个左值,但没有地址,它不是一个对象。
"rvals 可以通过 rval 引用来修改" 首先,rvalues 是表达式。表达式不被修改,对象被修改。 int
类型的右值不引用对象。右值reference 显然是一个左值,因为声明为引用的名称总是左值。而且这个右值引用显然不是指一个右值,它指的是一个对象,因为所有的引用都指代对象。所以你几乎没有在这里修改右值。
我只是说通过rval表达式创建的对象可以通过rval引用进行修改,当然在我的帖子中并不明显,我会编辑它
如果你想要一个可修改的右值,这里有一个:std::string() = "Hello, world";
【参考方案7】:
RValues 是不可操作的内存区域
错了。右值绝对是可变的。在 C++03 中这样做是一件令人头疼的事情,但可以合法地进行——在 C++11 中这是非常普遍的。
右值是产生即将死亡的事物的表达式。这是他们的定义属性。因此,您可以使用 C++11 的右值引用来窃取他们的资源而无需担心,或者如果您不顾一切,可以在 C++03 中“交换”。这使得它们在许多情况下更正确,并且在很多很多情况下更快。
【讨论】:
以上是关于RValue 由啥构成?的主要内容,如果未能解决你的问题,请参考以下文章
Spark 中的 executorRunTime 由啥组成?