我正在学习右值参考,教程告诉我:
很明显,在x和x之间交换资源指针(句柄)会更好,也更有效率 临时的,然后让临时的析构函数破坏x的原始资源。X foo(); X x; x = foo();
换句话说,在右侧的特殊情况下 赋值是一个右值,我们希望复制赋值运算符起作用 像这样。
那么,这是否意味着函数的返回值在默认情况下始终是常量,从而是一个rvalue?如果是:它们总是不变,还是有例外?
答案 0 :(得分:3)
那么,这是否意味着函数的返回值在默认情况下始终是常量,从而是一个rvalue?如果是:它们总是不变,还是有例外?
没有。如果他们没有返回引用类型(cv T&
或cv T&&
),则它们是rvalues。如果它们的返回类型是const限定的,它们是常量。
这意味着函数X foo()
的返回值是rvalue(prvalue,如果你想要 new standardese ),而不是常量。此外,在像x = foo()
这样的表达式中,我们通常不关心赋值期间的临时变化,这几乎是移动语义背后的想法。
答案 1 :(得分:3)
Rvalue-ness和constant-ness不是同义词,而是有点正交。具有以下定义:
struct X {};
const X x;
const X f();
int X();
我们可以对以下表达式进行分类:
x; // constant lvalue
f(); // constant rvalue
g(); // non-constant rvalue
截至您的特定问题:不,并非所有的右值表达式都是常量。
答案 2 :(得分:1)
您可能会混淆类型,对象和表达式。只有表达式具有左值/右值的概念。 表达式 foo();
是X
类型的右值。因此,语句x = foo();
将调用 - 如果可能 - X::operator=(X &&)
的成员函数x
。如果失败了,它将绑定到标准X::operator=(X const &)
,因为rvalues绑定到const-references。
请注意,理论上可以使用常量rvalues,例如,如果您将函数声明为X const bar();
。然后,bar()
不会绑定到X&&
,而只会绑定到X const &&
(以及X const &
)。但是,在实践中没有用这个。
答案 3 :(得分:1)
参见this previous question,它告诉我们rvalue表达式既不是const
类型的隐式表达式,也不是它们所代表的对象本身也是不可变的。
但是, 未定义(或禁止 - 我忘记了哪些)在某些情况下通过右值修改对象。这似乎产生了一种通过rvalue访问的对象的条件固有的不变性,并且评估函数调用的结果通常是 - 虽然并非总是如此! - 一个右值表达式。
答案 4 :(得分:1)
§5.2.2/ 10(在N3225中)陈述:
如果结果类型是左值引用类型或对函数类型的右值引用,则函数调用是左值;如果结果类型是对象类型的右值引用,则为xvalue,否则为prvalue。