以下链接提供了4种形式的引用折叠(如果我是正确的,这些是唯一的4种形式):http://thbecker.net/articles/rvalue_references/section_08.html.
从链接:
- A &&成为A&
- A &&&成为A&
- A &&&成为A&
- A && &&成为A &&
虽然我可以做出有根据的猜测,但我想简要解释这些参考折叠规则背后的基本原理.
一个相关的问题,如果可能的话:在典型的实际用例中,这些STL实用程序(例如,等)在C++ 11内部使用这些引用折叠规则吗?(注意:我特别询问C++ 11中是否使用了引用折叠规则,而不是C++ 03或更早版本.)std::move()std::forward()
我问这个相关的问题,因为我知道这样的C++ 11实用程序std::remove_reference,但我不知道是否与std::remove_referenceC++ 11中常规使用的引用相关的实用程序,以避免需要引用 - 折叠规则,或者它们是否与参考折叠规则一起使用.
Nic*_*las 33
参考折叠规则(除了A& & -> A&,这是C++ 98/03)存在的原因之一是:允许完美的转发工作.
"完美"转发意味着有效地转发参数,就好像用户直接调用了函数一样(减去elision,它被转发打破).用户可以传递三种值:lvalues,xvalues和prvalues,接收位置可以通过三种方式获取值:by value,by(可能是const)左值引用,以及by(可能是const)rvalue参考.
考虑这个功能:
template<class T>
void Fwd(T &&v) { Call(std::forward<T>(v)); }
Run Code Online (Sandbox Code Playgroud)
如果Call按值获取其参数,则必须在该参数中进行复制/移动.哪一个取决于传入的值是什么.如果传入值是左值,则它必须复制左值.如果传入的值是一个rvalue(统称为xvalues和prvalues),那么它必须从它移动.
如果调用Fwd与左值,C++的类型推演规则意味着T会推导出Type&,这里Type是左值的类型.显然,如果左值是const,它将被推断为const Type&.参考崩溃规则意味着Type & &&变成Type &了v,一个左值引用.这正是我们需要调用的内容Call.使用左值引用调用它将强制复制,就像我们直接调用它一样.
如果Fwd使用rvalue 调用(即:Type临时表达式或某些Type&&表达式),T则将推断为Type.引用折叠规则给了我们Type &&,它引发了一个移动/复制,这几乎就像我们直接调用它一样(减去elision).
如果Call通过左值引用获取其值,则它应该仅在用户使用左值参数时可调用.如果它是一个const-lvalue引用,那么它可以被任何东西调用(lvalue,xvalue,prvalue).
如果你Fwd用左值调用,我们再次得到Type&它的类型v.这将绑定到非const左值引用.如果我们用const左值调用它,我们得到const Type&,它只会绑定到一个const左值引用参数Call.
如果你Fwd用xvalue 打电话,我们再次得到Type&&它的类型v.这会不会让你调用一个函数,它接受一个非const左值作为x值不能绑定到一个非const左值参考.它可以绑定到const lvalue引用,所以如果Call使用a const&,我们可以Fwd用xvalue 调用.
如果你Fwd用prvalue 打电话,我们再次得到Type&&,所以一切都像以前一样.你不能将临时函数传递给带有非常量左值的函数,因此我们的转发函数同样会尝试这样做.
如果Call通过右值引用获取其值,则只有在用户使用xvalue或rvalue参数时才能调用它.
如果你Fwd用左值调用,我们就会得到Type&.这不会绑定到右值引用参数,因此会产生编译错误.A const Type&也不会绑定到右值引用参数,因此它仍然失败.如果我们Call直接用左值调用,这正是会发生的事情.
如果你Fwd使用xvalue 打电话,我们会得到Type&&,这是有效的(cv-qualification仍然很重要).
使用prvalue也是如此.
std :: forward本身以类似的方式使用引用折叠规则,以便将传入的右值引用作为xvalues(函数返回值为Type&&xvalues)和传入的左值引用传递为lvalues(返回Type&).
规则实际上非常简单.Rvalue reference是对某些临时值的引用,该临时值不会超出使用它的表达式 - 与lvalue reference持久化数据的引用相反.因此,如果您有对持久数据的引用,则无论您将其与哪些引用结合使用,实际引用的数据都是左值 - 这涵盖了前3个规则.第四条规则也是自然的 - 对右值引用的右值引用仍然是对非持久数据的引用,因此产生了右值引用.
是的,C++ 11实用程序依赖于这些规则,链接提供的实现与实际标题匹配:http://en.cppreference.com/w/cpp/utility/forward
是的,在使用std::move和std::forward实用程序时,正在应用折叠规则以及模板参数推导规则,就像链接中所解释的那样.
类型特征的使用remove_reference实际上取决于您的需求; move并forward为最随意的案件提供保险.
| 归档时间: |
|
| 查看次数: |
10944 次 |
| 最近记录: |