(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 。

从链接:

  1. A&&成为A&
  2. A &&&成为A&
  3. A &&&成为A&
  4. 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::movestd::forward工具时,正如应用在链接中所解释的那样,崩溃规则和模板参数推导规则一起被应用。

remove_reference等types特征的使用实际上取决于你的需求; moveforward封面为最偶然的情况。