书中关于"rvalue"和"rvalue reference"的混淆

3

我搜索了"functional programming in c++"书籍,只得到了4个不相关的结果。

我正在阅读Ivan Čukić的Functional Programming in C++,在第118页有一句话我不确定是否理解正确。这一部分讲述成员函数的右值引用和左值引用重载,而这句话是指使用&&引用类型限定符的第二个重载:

第二个重载将被调用,用于你可以从中借用数据的对象--临时对象和其他右值引用

我的疑问如下:

  • 斜体部分首先让我感到困惑,因为如果不是临时对象,那还能是什么呢?但可能这只是因为我还没有完全理解xvalues的概念;
  • 粗体的单词真的让我感到困惑,因为只有删除这个单词后,这句话才对我有意义。
下面的代码是为了支持我的理解。
实际上,我的理解是,如果我说“rvalue引用”,我指的是函数参数(因此它有一个名称;例如,在自由函数f的声明中,a)声明为rvalue引用到实际参数,或者我已经声明的变量(因此它有一个名称;例如:rr)作为另一个变量的rvalue引用;(值得一提的是,引用的实体必须是rvalues,否则引用将无法绑定)。无论哪种情况,由于它有一个名称,调用成员函数f,将导致调用lvalue重载,不是吗?
那么书中是否存在措辞错误,还是我漏掉了什么?
#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个回答

1

这个粗体的词让我感到困惑,只有删除这个词,整个句子才有意义。

我同意。我认为更准确的句子应该是:

第二个重载将被调用,对象从中您被允许读取数据——rvalues(prvalues或xvalues)。

Rvalue reference 用于类型,rvalue 用于value categories,它们是独立的概念。在这种情况下,调用哪个重载取决于值类别,即要调用的对象是lvalue还是rvalue,与其类型无关。

斜体部分首先让我感到困惑,因为如果不是临时变量,那还能是什么呢?但可能这只是因为我还没有很好地理解什么是xvalues。

是的,xvalues 也是 rvalues。给定 int x = 0;std::move(x) 是一个 xvalue,但它不是一个临时对象。


还要注意,表达式永远不会具有引用类型。任何本应具有引用类型的表达式(例如,当函数的返回类型被指定为引用类型时的函数调用)都将从其类型中删除该引用,并相应地调整其值类别。 - HTNW
所以表达式 std::move(x) 是指向 x 的右值引用类型,其值类别是右值。我是正确的吗? - Enlico
@HTNW 你需要支持你的说法或者更加具体。decltype(fn()) 明确返回一个引用类型,声明为 T& fn() - Zuodian Hu
3
decltype并不能真正给出表达式的类型!decltype通过使用引用类型来结合类型和值类别信息:prvalues不带引用,lvalues带有&,xvalues带有&&。我的早期评论直接基于标准decltype“撒谎”的事实也来自标准 - HTNW
@EnricoMariaDeAngelis 不是的。在这个答案中给出的例子中,std::move(x) 的类型是 int,类别是 xvalue。表达式 x 本身的类型是 int,类别是 lvalue。std::move 将类别从 lvalue 转换为 xvalue,而不改变类型。"rvalue" 是 "prvalue 或 xvalue" 的简写;说 std::move(x) 是一个 rvalue 是正确的,但更具体地说它是一个 xvalue。从 lvalue 到 xvalue 的转换以及从 xvalue 到 lvalue 的转换都是零成本的,这促使我们说它们实际上是同一种东西,只是意图不同。 - HTNW
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接