我正在尝试理解有关传输语义、右值、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 的类型到底是什么?这里谁错了?
我是这么想的:
50
是右值,计算表达式 50
返回右值引用int&& x
是左值,因此返回左值引用 (?)这是正确的推理方式吗?
还是boost库错了?或者也许编译器返回了一个严重的错误? 为什么错误按摩是
int
类型的左值而不是 int&
?
如果参数在函数内充当左值引用(正如我链接的堆栈线程中所述),为什么错误不显示
int&
?
我的意思不仅仅是为了得到函数内部
x
的类型的答案。我更感兴趣的是理解为什么 boost 库说的是一件事,错误说的是另一件事,而 C++ 的理论知识又说的是另一件事。
您正在混合两个不同的概念,并且感到非常困惑。
x
内部的参数f
是右值引用,因为它是这样声明的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
,这正是它告诉您的。
我的意思不仅仅是为了得到函数内部
的类型的答案。我更感兴趣的是理解为什么 boost 库说的是一件事,错误说的是另一件事,而 C++ 的理论知识又说的是另一件事。x
参数
x
的类型为int&&
,表达式x
的类型为int
。
您使用的 boost 实用程序基于参数的类型,而不是基于表达式的类型 x
。
如果您愿意,您可以获得表达式
x
的类型:
std::remove_reference_t<decltype(x)>
这显然与
decltype(x)
不同,后者产生声明的类型。