C++11:为什么右值引用参数隐式转换为左值
C++11: Why rvalue reference parameter implicitly converted to lvalue
以下是我的问题的简单代码,
void overloaded (int&& x) {
cout << "[rvalue]";
}
template <class T>
void fn (T&& x) {
overloaded(x);
}
int main() {
fn(0);
return 0;
}
我遇到编译错误
cannot bind ‘int
’ lvalue to ‘int&&
’
overloaded(x);
我在这里很困惑,x
作为右值引用传递给 fn()
。但是为什么 fn()
中的 overload()
调用抱怨 x
是左值?
第一,fn
的 x
参数不是 r-value 引用,it's a "universal reference" (yes, this is rather confusing)。
第二,当你给一个对象一个名字时,这个名字不是 r-value 除非明确地 "fixed",要么用 std::move
(使它成为 r-value 引用,总是),或使用 std::forward
(在通用引用的情况下将其转换回其原始类型)。如果你想避免被投诉,请使用std::forward
转发为原始类型:
template <class T>
void fn (T&& x) {
overloaded(std::forward<T>(x));
}
你不是 "passing x
as an rvalue reference",因为那句话根本说不通。
以下是有关 C++ 中类型和表达式分类的精选事实:
有对象类型,也有引用类型。 (还有其他几种类型。)
变量可以是对象或引用。
表达式有类型,那些类型(几乎)总是对象类型,从不引用。 (这就是为什么你的 "passing something as a reference" 语句没有意义;你传递 参数 并且参数总是表达式。)表达式可以是左值、xvalues 或 prvalues。
左值引用绑定到左值。右值引用绑定到右值。 (右值要么是纯右值,要么是 x 值。)
id-expression 命名变量或参数是左值。 (如果您愿意,可以是 "thing with a name" 或 "a location"。)
因此在表达式 overloaded(x)
中,子表达式 x
是一个左值,它不绑定到需要右值的函数(由于其右值引用参数)。
"lvalue reference"和"rvalue reference"中的"l"和"r"是指引用可以绑定的值的类别,不是 到 id-expression 命名此引用类型的变量的类别。
您可以将左值转换为右值,方法是将其转换为亡值;这很方便地封装到 type-deducing cast helper std::move
.
以下是我的问题的简单代码,
void overloaded (int&& x) {
cout << "[rvalue]";
}
template <class T>
void fn (T&& x) {
overloaded(x);
}
int main() {
fn(0);
return 0;
}
我遇到编译错误
cannot bind ‘
int
’ lvalue to ‘int&&
’overloaded(x);
我在这里很困惑,x
作为右值引用传递给 fn()
。但是为什么 fn()
中的 overload()
调用抱怨 x
是左值?
第一,fn
的 x
参数不是 r-value 引用,it's a "universal reference" (yes, this is rather confusing)。
第二,当你给一个对象一个名字时,这个名字不是 r-value 除非明确地 "fixed",要么用 std::move
(使它成为 r-value 引用,总是),或使用 std::forward
(在通用引用的情况下将其转换回其原始类型)。如果你想避免被投诉,请使用std::forward
转发为原始类型:
template <class T>
void fn (T&& x) {
overloaded(std::forward<T>(x));
}
你不是 "passing x
as an rvalue reference",因为那句话根本说不通。
以下是有关 C++ 中类型和表达式分类的精选事实:
有对象类型,也有引用类型。 (还有其他几种类型。)
变量可以是对象或引用。
表达式有类型,那些类型(几乎)总是对象类型,从不引用。 (这就是为什么你的 "passing something as a reference" 语句没有意义;你传递 参数 并且参数总是表达式。)表达式可以是左值、xvalues 或 prvalues。
左值引用绑定到左值。右值引用绑定到右值。 (右值要么是纯右值,要么是 x 值。)
id-expression 命名变量或参数是左值。 (如果您愿意,可以是 "thing with a name" 或 "a location"。)
因此在表达式 overloaded(x)
中,子表达式 x
是一个左值,它不绑定到需要右值的函数(由于其右值引用参数)。
"lvalue reference"和"rvalue reference"中的"l"和"r"是指引用可以绑定的值的类别,不是 到 id-expression 命名此引用类型的变量的类别。
您可以将左值转换为右值,方法是将其转换为亡值;这很方便地封装到 type-deducing cast helper std::move
.