传递给函数的右值是否仍然是右值?

问题描述 投票:0回答:1

我正在尝试理解有关传输语义、右值、x值、纯右值等的所有内容。 我有以下功能:

void f(int&& x, int i)
{
    std::cout << boost::typeindex::type_id_with_cvr<decltype(x)>().pretty_name();
}

然后我得到输出:

int&&

好。那么,

x
,即使在函数内部,也是一个右值引用?

boost::typeindex::type_id_with_cvr
函数表明,即使在函数内,输入右值引用参数仍然是右值引用。 然而,从我在互联网上读到的内容来看,传递给函数的右值在函数内部变成了左值引用。

来自参数的右值引用仅用于从调用者的角度选择函数,它的行为类似于函数内部的左值引用

作为参数传递的右值在函数内是否被视为左值?

因此,当在函数

f
内部时,我尝试再次调用函数
f
;突然发现
x
根本不再是右值:

void f(int&& x, int i)
{
     std::cout << boost::typeindex::type_id_with_cvr<decltype(x)>().pretty_name();
     i++;
     if (i < 10)
     {
         f(x, i);
     }
}
int main(int, char**)
{
     int i = 0;
     f(50,i);
}

结果:“无法将‘int&&’类型的右值引用绑定到‘int’类型的左值”。

那么函数内 x 的类型到底是什么?这里谁错了?

我是这么想的:

  1. 50
    是右值,计算表达式
    50
    返回右值引用
  2. 右值引用
    int&& x
    是左值,因此返回左值引用 (?)

这是正确的推理方式吗?

还是boost库错了?或者也许编译器返回了一个严重的错误? 为什么错误按摩是

int
类型的左值而不是
int&

如果参数在函数内充当左值引用(正如我链接的堆栈线程中所述),为什么错误不显示

int&

我的意思不仅仅是为了得到函数内部

x
的类型的答案。我更感兴趣的是理解为什么 boost 库说的是一件事,错误说的是另一件事,而 C++ 的理论知识又说的是另一件事。

c++ rvalue-reference
1个回答
0
投票

您正在混合两个不同的概念,并且感到非常困惑。

  • 声明可以是引用(例如左值引用、右值引用)
    • 例如,
      x
      内部的参数
      f
      是右值引用,因为它是这样声明的
  • 表达式具有值类别(左值、x值、纯右值)
    • 例如,表达式
      x
      出现在
      f
      内部时是左值(除非它位于
      return
      语句中)
在谈论函数参数时,

x
是右值引用,但在谈论其他代码中出现的表达式时,
x
是左值。当您了解其中的差异时,您所有的问题就很容易回答:

好。那么,

x
,即使在函数内部,也是一个右值引用?

是的,函数

x
的参数
f
是右值引用。 这正是
decltype(x)
为您提供的:声明类型,顾名思义。

但是,从我在互联网上读到的内容来看,传递给函数的右值在函数内部变成了左值引用。

这是不准确的。当函数参数出现在某个表达式中时,它们是左值,但它们的类型完全取决于您如何声明函数。

那么函数内部的

x
到底是什么类型,谁错了?

表达式

x
的类型为
int
,表达式
x
的值类别为左值。函数参数
x
的类型是
int&&

50
是一个右值,计算表达式
50
返回一个右值引用

50
是纯右值,但评估它不会产生引用。它生成一个类型为
int
的临时对象。

右值引用 int&& x 是左值,因此返回左值引用 (?)

这句话没有道理。类型本质上并不是左值或右值。 值类别取决于使用

x
的表达式和上下文。

如果参数在函数内充当左值引用(正如我链接的堆栈线程中所述),为什么错误不显示

int&

因为参数

x
的类型是
int&&
。如果您使用
decltype
,这正是它告诉您的。

我的意思不仅仅是为了得到函数内部

x
的类型的答案。我更感兴趣的是理解为什么 boost 库说的是一件事,错误说的是另一件事,而 C++ 的理论知识又说的是另一件事。

参数

x
的类型为
int&&
,表达式
x
的类型为
int
。 您使用的 boost 实用程序基于参数的类型,而不是基于表达式的类型
x

如果您愿意,您可以获得表达式

x
的类型:

std::remove_reference_t<decltype(x)>

这显然与

decltype(x)
不同,后者产生声明的类型。

© www.soinside.com 2019 - 2024. All rights reserved.