(1)A && – > A&,(2)A &&&> A&,(3)A &&&&> A&,和(4)A && && – > A &&
下面的链接提供了4种forms的引用崩溃(如果我是正确的,这些是唯一的4种forms): http : //thbecker.net/articles/rvalue_references/section_08.html 。
从链接:
- A&&成为A&
- A &&&成为A&
- A &&&成为A&
- A && &&变成A &&
虽然我可以做出一个有教养的猜测,但我想简要解释一下这些参考折叠规则背后的基本原理。
一个相关的问题,如果我可能:在典型的现实世界中,这些引用崩溃规则是由C ++ 11在内部被诸如std::move()
, std::forward()
类的STL实用程序使用用例? (注意:我具体询问在C ++ 11中是否使用引用合并规则,而不是C ++ 03或更早版本)。
我问这个相关的问题,因为我知道这样的C + + 11实用程序作为std::remove_reference
,但我不知道是否引用相关的工具,如std::remove_reference
在C + + 11中经常使用,以避免需要用于引用合拢规则,或者它们是否与引用合拢规则一起使用 。
存在引用合并规则(除了A& & -> A&
,这是C ++ 98/03)存在的原因之一:允许完美的转发工作。
“完美”转发意味着有效地转发参数,就好像用户直接调用了该函数(减去被转发破坏的elision)。 用户可以传递的值有三种:lvalues,xvalues和prvalues,接收位置可以有三种方式取值:value,by(可能是const)lvalue引用,by(可能是const)rvalue参考。
考虑这个function:
template<class T> void Fwd(T &&v) { Call(std::forward<T>(v)); }
按价值
如果Call
通过值获取其参数,则必须在该参数中进行复制/移动。 哪一个取决于传入值是什么。 如果传入的值是一个左值,那么它必须复制左值。 如果传入的值是一个右值(它们共同是xvalues和prvalues),那么它必须从它移出。
如果你用左值调用Fwd
,C ++的types推导规则意味着T
将被推导为Type&
,其中Type
是左值的types。 显然,如果左值是const
,则它将被推导为const Type&
。 参考折叠规则意味着Type & &&
变成Type &
for v
,一个左值引用。 这正是我们需要Call
。 用一个左值引用来调用它会强制一个副本,就像我们直接调用它一样。
如果你用一个xvalue(即:某些Type&&
expression式)调用Fwd
,那么T
将被推导为Type&&
。 参考折叠规则指出Type && &&
变成了Type&&
,这就是我们需要调用Call
。 用非const的右值引用调用它将强制移动/复制,就像我们直接调用它一样。
如果用prvalue(即: Type
临时expression式)调用Fwd
,则T
将被推断为Type
。 参考折叠规则给了我们Type &&
,它再次引发一个移动/复制,就像我们直接调用它(减去elision)一样。
由左值参考
如果Call
通过左值引用取值,那么只有在用户使用左值参数时才可以调用它。 如果它是一个const-lvalue引用,那么它可以被任何东西(左值,左值,右值)调用。
如果你用左值调用Fwd
,我们再次获得Type&
作为v
的types。 这将绑定到一个非const的左值引用。 如果我们用一个常量左值来调用它,我们得到const Type&
,它只会绑定到Call
一个常量左值引用参数。
如果你用一个xvalue调用Fwd
,我们再次得到Type&&
作为v
的types。 这不会允许你调用一个非const的左值的函数,因为xvalue不能绑定到一个非const的左值引用。 它可以绑定到const左值引用,所以如果Call
使用const&
,我们可以用xvalue调用Fwd
。
如果你用prvalue给Fwd
打电话,我们再次得到Type&&
,所以一切和以前一样。 你不能把一个临时函数传给一个非const的左值的函数,所以我们的转发函数也会试图这样做。
由右值引用
如果Call
通过右值引用获取值,那么只有当用户使用xvalue或rvalue参数时才能调用它。
如果你用左值调用Fwd
,我们得到Type&
。 这不会绑定到一个右值引用参数,所以编译错误的结果。 一个const Type&
也不会绑定到一个右值引用参数,所以它仍然失败。 而这正是如果我们用一个左值直接调用Call
话会发生什么情况。
如果你用一个xvalue调用Fwd
,我们得到Type&&
,这个工作(cv-qualification当然还是很重要)。
使用prvalue也是一样。
的std ::前进
std :: forward本身以类似的方式使用引用折叠规则,以便将传入的右值引用作为xvalues( Type&&
是xvalues的函数返回值)和传入的左值引用作为左值(返回Type&
)。
规则其实很简单。 Rvalue reference
是对一些临时值的引用,它不会超出使用它的expression式 – 与引用持久数据的lvalue reference
相比。 所以,如果你有一个持久化数据的引用,不pipe你将其与其他引用合并,实际引用的数据是一个左值 – 这涵盖了前3条规则。 第四条规则也是自然的 – 对右值引用的右值引用仍然是对非永久性数据的引用,因此产生右值引用。
是的,C ++ 11实用程序依赖于这些规则,链接提供的实现与实际标题匹配: http : //en.cppreference.com/w/cpp/utility/forward
是的,当使用std::move
和std::forward
工具时,正如应用在链接中所解释的那样,崩溃规则和模板参数推导规则一起被应用。
remove_reference
等types特征的使用实际上取决于你的需求; move
和forward
封面为最偶然的情况。