繁体   English   中英

当const引用参数绑定到右值时,它是否保持其“状态”?

[英]Does an rvalue keep its “status” when a const reference parameter binds to it?

T为任意类型。 考虑一个采用const [lvalue]引用的const

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提供右值引用重载?

值类别应用于表达式 ,而不是对象。 f中的obj是一个左值表达式,因此将被视为此类。 注意g中的obj 也是一个左值表达式; 如果表达式是对象的名称,则为左值。

您正在谈论的能力正是转发引用存在的原因:这样就可以通过函数调用来保留参数表达式的值类别的复制/移动方面。 f必须成为以下形式的template<typename T> void f(T&& t); ,并且在将其传递给g时必须使用std::forward

当您将引用的名称用作表达式时,该表达式始终是左值。 无论是左值引用还是右值引用。 引用是用左值还是右值初始化也无关紧要。

int &&x = 1;
f(x); // Here `x` is lvalue.

因此,在void f(const T &obj) {...} ,不管您作为参数传递什么, obj始终是左值。

还要注意,值类别是在编译时确定的。 由于f不是模板,因此其中的每个表达式的值类别都不能取决于您传递的参数。

从而:

如果将rvalue传递给f ,则将调用g的rvalue参考重载。

没有。

如果f调用了一个按值接受T实例的函数,则void h(T obj); 并且T有一个move构造函数(即T(T &&); ),该move构造函数将被称为

没有。

总而言之,如果我们想确保在对一个右值调用f时,右值引用在传递时保持其右值“状态”,那么我们是否必须为f提供右值引用重载?

提供过载是一种选择。 请注意,在这种情况下,您必须在rvalue重载中显式调用std::move

另一个选择是使用转发引用 ,如Nicol Bolas建议的那样:

template <typename T> void f(T &&t)
{
    g(std::forward<T>(t));
}

在这里, std::forward本质上是一种“条件move ”。 如果传递了右值,它将移动t ,否则不执行任何操作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM