以下链接提供了 4 种引用折叠形式(如果我是对的,这些是仅有的 4 种形式):http://thbecker.net/articles/rvalue_references/section_08.html .
从链接:
- A& & becomes A&
- A& && becomes A&
- A&& & becomes A&
- A&& && becomes A&&
虽然我可以做出有根据的猜测,但我想对这些引用折叠规则背后的基本原理进行简要解释。
一个相关的问题,如果可以的话:是否使用了这些引用折叠规则在 C++11 中 在内部由诸如
std::move()
之类的 STL 实用程序使用, std::forward()
等,在典型的现实世界用例中? (注意:我特别询问 C++11 中是否使用了引用折叠规则,而不是 C++03 或更早版本。)我问这个相关的问题是因为我知道这样的 C++11 实用程序,如
std::remove_reference
,但不知道是否引用了std::remove_reference
等相关实用程序在 C++11 中经常使用,以避免需要引用折叠规则,或者它们是否与引用折叠规则一起使用。
最佳答案
引用折叠规则(除了 A& & -> A&
,它是 C++98/03)存在的原因之一是:允许完美转发工作。
“完美”转发意味着有效地转发参数,就像用户直接调用该函数一样(减去省略,转发被破坏)。用户可以传递三种值:lvalues、xvalues和prvalues,接收位置可以通过三种方式取值:by value、by(可能是const)左值引用和by(可能是const)右值引用。
考虑这个函数:
template<class T>
void Fwd(T &&v) { Call(std::forward<T>(v)); }
按值(value)
如
Call
按值获取其参数,然后必须在该参数中进行复制/移动。哪一个取决于传入的值是什么。如果传入值是左值,则它必须复制左值。如果传入的值是一个右值(它们统称为 xvalues 和 prvalues),那么它必须从中移动。如果您调用
Fwd
对于左值,C++ 的类型推导规则意味着 T
将被推导出为 Type&
, 其中 Type
是左值的类型。显然如果左值是 const
, 将推导出为 const Type&
.引用折叠规则意味着Type & &&
变成 Type &
为 v
,一个左值引用。这正是我们需要调用的Call
.使用左值引用调用它会强制复制,就像我们直接调用它一样。如果您调用
Fwd
使用右值(即: Type
临时表达式或某些 Type&&
表达式),然后 T
将被推导出为 Type
.引用折叠规则给了我们 Type &&
,这会引发移动/复制,这几乎就像我们直接调用它一样(减去省略)。通过左值引用
如
Call
通过左值引用获取它的值,那么它应该只在用户使用左值参数时才可调用。如果它是一个 const-lvalue 引用,那么它可以被任何东西(左值、xvalue、prvalue)调用。如果您调用
Fwd
使用左值,我们再次得到 Type&
作为v
的类型.这将绑定(bind)到非常量左值引用。如果我们用 const 左值调用它,我们会得到 const Type&
,它只会绑定(bind)到 Call
中的 const 左值引用参数.如果您调用
Fwd
使用 xvalue,我们再次得到 Type&&
作为v
的类型.这将不允许您调用采用非常量左值的函数,因为 xvalue 不能绑定(bind)到非常量左值引用。它可以绑定(bind)到一个 const 左值引用,所以如果 Call
使用了 const&
, 我们可以调用 Fwd
与 xvalue。如果您调用
Fwd
使用纯右值,我们再次得到 Type&&
,所以一切都像以前一样。您不能将临时值传递给采用非常量左值的函数,因此我们的转发函数同样会在尝试这样做时窒息。通过右值引用
如
Call
通过 rvalue 引用获取其值,那么它应该只在用户使用 xvalue 或 rvalue 参数时才可调用。如果您调用
Fwd
使用左值,我们得到 Type&
.这不会绑定(bind)到右值引用参数,因此会导致编译错误。 A const Type&
也不会绑定(bind)到右值引用参数,所以它仍然失败。这正是我们调用 Call
时会发生的情况。直接用左值。如果您调用
Fwd
使用 xvalue,我们得到 Type&&
,这很有效(当然,cv 资格仍然很重要)。使用纯右值也是如此。
标准::转发
std::forward 本身以类似的方式使用引用折叠规则,以便将传入的右值引用作为 xvalues(函数返回值
Type&&
是 xvalues)和传入的左值引用作为左值传递(返回 Type&
)。
关于c++ - 要求的引用折叠规则的简明解释 : (1) A& & -> A& , (2) A& && -> A& ,(3) A&& & -> A& ,以及 (4) A&& && -> A&&,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13725747/