书中“右值”和“右值引用”之间的混淆
Posted
技术标签:
【中文标题】书中“右值”和“右值引用”之间的混淆【英文标题】:Confusion between "rvalue" and "rvalue reference" in book 【发布时间】:2020-08-24 06:33:03 【问题描述】:(我搜索了[c++]《c++中的函数式编程》一书,只给出了4个不相关的结果。)
我正在阅读Ivan Čukić 的C++ 中的函数式编程,在第118 页有一句话我不确定我是否理解。该部分是关于成员函数的右值和左值重载,句子如下,其中第二个重载是使用&&
引用类型限定符的那个:
第二个重载将在允许您从中替代数据的对象上调用——临时对象和其他右值引用。
我的疑惑是:
italic 中的部分首先让我感到困惑,就像 如果不是暂时的,它还能是什么?,但也许这只是因为我还没有'对什么是 xvalues 没有明确的理解; 粗体中的单词真的让我感到困惑,因为只有当我删除那个单词时,这句话才对我有意义。下面的代码是为了支持我的理解。
确实,我的理解是,如果我说右值引用,我说的是一个函数参数(所以它有一个名字;例如:a
in the free function f
' s 声明)声明为对实际参数的右值引用,或者我已声明的变量(因此它有一个名称;例如:rr
)作为对另一个变量的右值引用; (fwiw,两个引用的ed实体都必须是右值,否则引用不会绑定)。无论哪种情况,由于它有一个名称,因此在其上调用成员函数 f
会导致调用左值重载,不是吗?
所以这本书有什么用词错误还是我遗漏了什么?
#include <iostream>
struct A
void f() & std::cout << "lvalue\n"; // const & in the book, but it shouldn't make any difference
void f() && std::cout << "rvalue\n";
;
void f(A&& a) a.f(); // a is an lvalue (of type rvalue ref to)
int main()
A a; // "normal" object
A&& rr = A; // rvalue reference to a temporary (with life extended)
a.f();
A.f(); // only here I expect the rvalue overload to be called, and this is the case
f(A);
rr.f();
【问题讨论】:
【参考方案1】:粗体中的词真的让我感到困惑,因为只有当我删除那个词时,这句话才对我有意义。
我同意。 IMO 更准确地说,这句话应该是
第二个重载将在允许您替代数据的对象上调用 - 右值(右值或 xvalue)。
右值引用用于类型,右值用于value categories,它们是独立的东西。在这种情况下,调用哪个重载取决于值类别,即要调用的对象是左值还是右值,与它的类型无关。
斜体中的部分首先让我感到困惑,就像在如果不是暂时的,那还能是什么?但也许这只是因为我还没有'对什么是 xvalues 没有明确的理解;
是的,xvalues 也是 rvalues。鉴于 int x = 0;
std::move(x)
是一个 xvalue 但它不是临时的。
【讨论】:
也许将 xvalues 视为就像左值一样是直观的(两者都是 glvalues 并且都引用现有对象),但唯一的区别是 intent。左值指的是您打算以后仍然可用的对象,而xvalue 指的是您不再“关心”的对象。 还要注意表达式从不有引用类型。任何具有引用类型的表达式(例如,当函数的返回类型作为引用类型给出时的函数调用)都会从其类型中删除该引用,并相应地调整其值类别。 @HTNW,非常感谢您提供支持您第二条评论的链接,因为它可以帮助我理解这个主题。 所以表达式std::move(x)
是对x
的右值引用类型,它的值类别是右值。我说的对吗?
@ZuodianHu decltype
不实际上给你表达式的类型! decltype
使用引用类型组合类型和值类别信息:prvalues 没有引用,lvalues 得到&
,xvalues 得到&&
。我之前的评论直接基于the standard。 decltype
“谎言”这一事实也取自the standard。以上是关于书中“右值”和“右值引用”之间的混淆的主要内容,如果未能解决你的问题,请参考以下文章