C++11中类型推导中的Rvalue参考
Rvalue Reference in Type Deduction in C++11
在C++11之前,模板类型的推导非常简单:
template <typename X>
void bar(X i) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
类型X将是调用方传入的任何类型的参数
现在,对于C++11,我读了一篇来自Scott Meyers的关于右值引用的文章。
它表示
template<typename T>
void f(T&& param);
在对作为通用引用的模板参数进行类型推导时,同一类型的左值和右值被推导为具有略微不同的类型。特别地,类型T的左值被推导为类型T&(即,对T的左值引用),而T类型的右值被推导为简单的T类型。
我想知道为什么T类型的左值被推导为T&而T型的右值被推导为简单的T型。
这只是需要记住的东西吗?或
唯一要回答的问题是,为什么T&
会导致T&
而不是T
(就像在"正常"类型的推导中一样)。对此,我想答案是"完美转发"
EDIT:更详细地说,考虑一个完美地转发类构造函数的情况:
struct Widget //... to stay in Scott Meyers terminology
{
double &x;
Widget(double &_x) : x(_x) {}
};
class Manager : public Widget
{
template<typename ... Args>
Manager(Args&& ... args) : Widget(std::forward<Args>(args) ...) {}
};
如果您通过调用Manager
double d=1.0;
Manager(d);
根据您提到的规则,Args&&...
的类型被推导为double &
。由此,Manager
类构造函数的行为与类似
Manager(double &d) : Widget(std::forward<double&>(d)) {}
std::forward<double &>(d)
的效果基本上是static_cast<double&&>((double &) d)
,根据参考折叠的规则,它仍然是(double &) (d)
。结果,构造函数变成
Manager(double &d) : Widget((double &) d) {}
这样,变量就可以正确地传递给类Widget
,并且还可以确保调用正确的构造函数——引用的构造函数。
相反,如果类型不是推断为double &
,而是推断为double
,则Manager
类构造函数的行为将类似
Manager(double &d) : Base(std::forward<double>(d)) {}
转化为
Manager(double &d) : Base((double &&) (d)) {}
也就是说,左值引用被强制转换为右值引用(就像应用了std::move
一样)。
这样,可能仍然可以使用引用,因为强制转换没有更改变量的地址。然而,现在您不能确定Widget
中是否调用了正确的构造函数——也可能有另一个构造函数使用右值引用,然后会被错误地调用。
我认为原因是T和T&表示作为参数类型出现时的左值;只是T表示左值为局部变量,而T&意思是"来自其他地方的左值的别名"。
一般函数在为T、T&,并且T&;,因为后者的语义与lvalues的语义大不相同。所以,如果你想要一个右值,你应该明确地声明它。
- RVALUE参考与const lVALUE参考作为参数之间的混淆
- 如何使对象通过RVALUE参考通过而没有复制
- RVALUE参考与LVALUE结合
- RVALUE参考和多态性
- 是转发参考是否仍然是RVALUE参考
- 在平等符号左侧使用RVALUE参考的规则是什么?
- 为什么const rvalue合格的std ::可选:: value()返回const rvalue参考
- C 11:为什么RVALUE参考参数隐式转换为LVALUE
- 模板功能不使用RVALUE参考实例化/接收呼叫
- 作为RVALUE参考与双移动值的传递
- rvalue参考vector :: push_back函数如何提高效率
- 函数返回rvalue参考是否有意义
- 用rvalue参考和变异模板bits bits bys blamda by
- 移动后通过rvalue参考返回
- 为什么STD :: MOVE将RVALUE参考作为参数
- 成员函数返回成员变量的RVALUE参考
- 反复调用MOVE,其中需要RVALUE参考
- 产生副本作为输入,以获取RVALUE参考
- C 接收const lvalue和rvalue参考参数,而无需过载
- rvalue参考绑定到std ::功能类型的LVALUE