令T
是任意类型。考虑一个带有const
[lvalue]引用的函数:
void f(const T &obj);
假设此函数在内部调用另一个函数,该函数具有右值引用重载:
void g(T &&obj);
如果我们将右值传递给f
,将g
调用右值引用重载,还是因为它已经“转换” /绑定到const
左值引用而失败了?
同样,如果f
调用的函数采用T
按值的实例,
void h(T obj);
并且T
具有move构造函数(即T(T &&);
),将调用move构造函数,还是将调用copy构造函数?
总而言之,如果我们想确保在调用f
右值时,右值引用传递时保持其右值“状态”,我们是否必须为它提供右值引用重载f
?
当您将引用的名称用作表达式时,该表达式始终是左值。无论是左值引用还是右值引用。引用是用左值还是右值初始化也没有关系。
int &&x = 1;
f(x); // Here `x` is lvalue.
所以void f(const T &obj) {...}
,obj
始终是一个左值,不管你通过什么作为参数。
还要注意,值类别是在编译时确定的。由于f
不是模板,因此其中每个表达式的值类别都不能取决于您传递的参数。
从而:
如果我们向传递右值
f
,则将g
调用右值引用重载
没有。
如果
f
调用的函数采用T
值的实例,void h(T obj);
并且T
具有移动构造函数(即T(T &&);
),则将调用移动构造函数
没有。
总而言之,如果我们想确保在调用
f
右值时,右值引用传递时保持其右值“状态”,我们是否必须为它提供右值引用重载f
?
提供过载是一种选择。请注意,在这种情况下,您必须显式调用std::move
右值重载。
另一种选择是使用转发引用,如Nicol Bolas建议的那样:
template <typename T> void f(T &&t)
{
g(std::forward<T>(t));
}
在这里,std::forward
本质上是作为“有条件的move
”。t
如果将右值传递给它,它将移动,否则不执行任何操作。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句