RValue 由啥构成?

Posted

技术标签:

【中文标题】RValue 由啥构成?【英文标题】:What constitutes of RValues?RValue 由什么构成? 【发布时间】:2011-12-21 06:34:11 【问题描述】:

RValues 是不可操作的内存区域,所以像整数这样的字面量被认为是 RValues。

    常量是否构成 RValues? const int x = 0; 至少可操作一次。 现在,编译器创建的临时对象也是 RValue,即使它们具有可操作的内存区域。为什么会这样? 因为它们不能被“用户”修改?是这个原因吗?

那么,“用户”无法操作的内存区域称为 RValue?

【问题讨论】:

【参考方案1】:

标量右值是计算为标量值的表达式,如 42i + k(而标量左值是计算为标量对象的表达式,如 i*int_ptrnumbers[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 由啥组成?

httpservletrequest对象由啥创建

Rails/Devise 会话中的warden 数据由啥组成?

Java虚拟机的启动时间由啥组成?

Galaxy Nexus 上的 LED 手电筒可由啥 API 控制?