C++ 当函数采用右值引用时,函数中该变量的类型是什么?

C++ 当函数采用右值引用时,函数中该变量的类型是什么?,c++,rvalue-reference,lvalue-to-rvalue,C++,Rvalue Reference,Lvalue To Rvalue,这是一个术语问题。如果我有这个: #include <vector> void g(std::vector<int>&& arg); void f0(std::vector<int>&& v) { static_assert(std::is_same<decltype(v), std::vector<int>&&>::value); // Looks like v is an

这是一个术语问题。如果我有这个:

#include <vector>

void g(std::vector<int>&& arg);

void f0(std::vector<int>&& v) {
    static_assert(std::is_same<decltype(v), std::vector<int>&&>::value); // Looks like v is an rvalue reference.
    static_assert(std::is_same<decltype((v)), std::vector<int>&>::value);
    static_assert(std::is_same<std::decay<decltype(v)>::type, std::vector<int>>::value);
    return g(std::move(v)); // Fine.
}
本地右值引用的作用方式相同:

void f2(std::vector<int>&& v) {
    std::vector<int>&& vv = std::move(v);
    static_assert(std::is_same<decltype(vv), decltype(v)>::value, "They are the same decltype. So being an argument isn't magic.");
    static_assert(std::is_same<decltype(vv), std::vector<int>&&>::value);
    static_assert(std::is_same<decltype((vv)), std::vector<int>&>::value);
    static_assert(std::is_same<std::decay<decltype(vv)>::type, std::vector<int>>::value);
    return g(vv); // Error: cannot bind rvalue reference of type 'std::vector<int>&&' to lvalue of type 'std::vector<int>'
}
void f2(std::vector&&v){
std::vector&&vv=std::move(v);
static_assert(std::is_same::value,“它们是相同的decltype。所以作为一个参数不是魔术。”);
静态断言(std::is\u same::value);
静态断言(std::is\u same::value);
静态断言(std::is\u same::value);
返回g(vv);//错误:无法将'std::vector&'类型的右值引用绑定到'std::vector'类型的左值
}

描述
v
类型的正确术语是什么?说
f0
采用右值引用是否正确?如果
v
是一个右值引用,那么什么术语可以说右值引用不能用来调用使用右值引用的函数呢?

你把类型和值类别混淆了,这在你的辩护中是非常容易做到的

是的,函数接受类型为“rvalue reference to
std::vector
”的参数。此引用可以从调用站点上类型为
std::vector
的右值表达式初始化

当您开始尝试使用函数时,函数中的表达式
v
的类型不是
std::vector&
;参考类的“衰变”。这只是参考文献工作机制的一部分。(在这方面,
decltype
有点奇怪。)出于所有的意图和目的,您最终得到了类型为
std::vector
的左值表达式。无论如何,在这一点上,类型是不相关的;关键是名称
v
是一个左值,要使其再次成为右值,需要
std::move

但是静态_断言表明它是一个右值,对吗


没有。“右值引用”描述了各种类型。“右值”是一个值类别。你可能想知道为什么他们选择了如此混乱的术语。我也是。

你把类型和价值类别混淆了,这在你看来是非常容易做到的

是的,函数接受类型为“rvalue reference to
std::vector
”的参数。此引用可以从调用站点上类型为
std::vector
的右值表达式初始化

当您开始尝试使用函数时,函数中的表达式
v
的类型不是
std::vector&
;参考类的“衰变”。这只是参考文献工作机制的一部分。(在这方面,
decltype
有点奇怪。)出于所有的意图和目的,您最终得到了类型为
std::vector
的左值表达式。无论如何,在这一点上,类型是不相关的;关键是名称
v
是一个左值,要使其再次成为右值,需要
std::move

但是静态_断言表明它是一个右值,对吗


没有。“右值引用”描述了各种类型。“右值”是一个值类别。你可能想知道为什么他们选择了如此混乱的术语。我也是。

名为
v
的变量的声明类型是
std::vector&
。此类型的内容为“对
std::vector的右值引用”

名称
v
可以出现在表达式中。表达式从来没有引用类型。但表达方式有其特殊性。当名称
v
出现在表达式中时,如
v[0]
所示,子表达式
v
具有类型
std::vector
,其值类别为左值。几乎所有的表达式都是这样(只是一个名称的表达式)

decltype(v)
给出变量
v
的声明类型

decltype(表达式)
给出:

  • 如果
    表达式
    是左值,则表示
    表达式
    类型的左值引用
  • 如果
    表达式
    是x值,则对
    表达式
    类型的右值引用
  • 如果
    expression
    为PR值,则
    expression
    的类型为PR值

更多详细信息请参见。

名为
v
的变量的声明类型是
std::vector&
。此类型的内容为“对
std::vector的右值引用”

名称
v
可以出现在表达式中。表达式从来没有引用类型。但表达方式有其特殊性。当名称
v
出现在表达式中时,如
v[0]
所示,子表达式
v
具有类型
std::vector
,其值类别为左值。几乎所有的表达式都是这样(只是一个名称的表达式)

decltype(v)
给出变量
v
的声明类型

decltype(表达式)
给出:

  • 如果
    表达式
    是左值,则表示
    表达式
    类型的左值引用
  • 如果
    表达式
    是x值,则对
    表达式
    类型的右值引用
  • 如果
    expression
    为PR值,则
    expression
    的类型为PR值

更多细节见。

基本上,命名的右值引用(类型)是左值(值类别)。基本上,命名的右值引用(类型)是左值(值类别)。
void f2(std::vector<int>&& v) {
    std::vector<int>&& vv = std::move(v);
    static_assert(std::is_same<decltype(vv), decltype(v)>::value, "They are the same decltype. So being an argument isn't magic.");
    static_assert(std::is_same<decltype(vv), std::vector<int>&&>::value);
    static_assert(std::is_same<decltype((vv)), std::vector<int>&>::value);
    static_assert(std::is_same<std::decay<decltype(vv)>::type, std::vector<int>>::value);
    return g(vv); // Error: cannot bind rvalue reference of type 'std::vector<int>&&' to lvalue of type 'std::vector<int>'
}