This question询问所有临时值是否为右值。
答案是否定的,因为如果我们考虑这个表达式:
const int &ri = 2 + 3;
然后,可以使用非常相同的临时(2 + 3)
,这是一个右值
作为后续表达式中的左值:
const int *pi = &ri;
所以这个临时不是(仅)一个右值。
然后逻辑语句temporary ==> rvalue
为假。
但是,我们不能写
const int &ri = &(2 + 3); // illegal, 2 + 3 -> temporary -> rvalue
或
int *i = &4; // illegal, 4 is an rvalue (literal)
或
int foo();
int *i = &foo(); // illegal, foo() -> temporary -> rvalue
因此我的问题是,我们能否在某个表达式中生成一个rvalue而没有
有临时或文字? rvalue ==> (temporary or literal)
是真的吗?
答案 0 :(得分:5)
产生临时对象的表达式是 r值。有一个特殊的规则允许const引用和r值引用绑定到r值,这会将临时对象的生命周期延长到引用的生命周期(见12.2(5)),但这不会使临时-object表达式中任何较小的r值。
但是,一旦绑定到引用,引用变量本身就有一个名称,因此引用表达式是l-lvalue。
不要混淆表达式,变量和对象。
答案 1 :(得分:3)
rvalue 和 lvalue 属性适用于表达式,而不适用于对象。表达式可以是左值或右值。过度简化产生值的表达式是 rvalue-expression ,产生对象的表达式是 lvalue-expression 。 左值到 rvalue 转换是读取对象的值的行为。
产生临时和文字的表达式都是 rvalue-expressions ,它们代表值而不是实际对象。
在你的例子中:
const int &ri = 2 + 3;
const int *pi = &ri;
表达式2+3
是用于初始化常量引用的 rvalue-expression 。根据语言,这意味着临时超出当前表达式的延长,直到引用超出范围。之后,在第二个表达式中,子表达式ri
是一个左值表达式,它引用临时对象,其生命周期已被扩展。
请注意,还有其他方法可以创建带有临时值的 rvalue表达式,例如调用一个产生引用的成员:
struct test {
test& thisTest() { return *this; }
};
test foo();
... foo().thisTest()
子表达式foo()
是 rvalue-expression ,但表达式foo().thisTest()
是左值表达式。它们都引用了一个临时对象,它将在完整表达式的末尾消失。