C++ 请简要解释参考折叠规则:(1)A&&-&燃气轮机;A&;;,(2) A&&&-&燃气轮机;A&;;,(3) A&&&-&燃气轮机;A&;;,及(四)A& ;&&&-&燃气轮机;A&&;

C++ 请简要解释参考折叠规则:(1)A&&-&燃气轮机;A&;;,(2) A&&&-&燃气轮机;A&;;,(3) A&&&-&燃气轮机;A&;;,及(四)A& ;&&&-&燃气轮机;A&&;,c++,stl,C++,Stl,下面的链接提供了引用折叠的4种形式(如果我认为这是仅有的4种形式是正确的话): 从链接: A&&变成A&& A&&&成为A& A&&&成为A& &&&&成为一个&& 虽然我可以做出一个有根据的猜测,但我想对每个引用崩溃规则背后的原理做一个简明的解释 一个相关的问题,如果我可以的话:这些引用折叠规则在C++11中是否在典型的实际用例中被诸如std::move()、std::forward()等STL实用程序内部使用?(注意:我特别询问C++11中是否使用了引用折叠规则,而不是C++03或更早版本。

下面的链接提供了引用折叠的4种形式(如果我认为这是仅有的4种形式是正确的话):

从链接:

  • A&&变成A&&
  • A&&&成为A&
  • A&&&成为A&
  • &&&&成为一个&&
  • 虽然我可以做出一个有根据的猜测,但我想对每个引用崩溃规则背后的原理做一个简明的解释

    一个相关的问题,如果我可以的话:这些引用折叠规则在C++11中是否在典型的实际用例中被诸如
    std::move()
    std::forward()
    等STL实用程序内部使用?(注意:我特别询问C++11中是否使用了引用折叠规则,而不是C++03或更早版本。)


    我问这个相关问题是因为我知道像
    std::remove_reference
    这样的C++11实用程序,但我不知道像
    std::remove_reference
    这样的与引用相关的实用程序是否在C++11中经常使用,以避免引用折叠规则的需要,或者它们是否与引用折叠规则一起使用。

    这些规则实际上非常简单
    Rvalue reference
    是对某个临时值的引用,该临时值不会超出使用它的表达式的范围-与引用持久数据的
    lvalue reference
    相反。因此,如果您有一个对持久化数据的引用,无论您将其与其他引用组合在一起,实际引用的数据都是一个左值-这涵盖了前3条规则。第四条规则也是自然的-右值引用到右值引用仍然是对非持久数据的引用,因此产生右值引用

    是的,C++11实用程序依赖于这些规则,链接提供的实现与实际标题匹配:

    是的,当使用
    std::move
    std::forward
    实用程序时,将应用折叠规则和模板参数推断规则,就像在链接中解释的那样


    类型特征的使用,例如
    remove\u reference
    实际上取决于您的需要<代码>移动和
    向前
    覆盖最常见的情况。

    参考折叠规则(除了C++98/03中的
    A&&->A&
    )的存在有一个原因:允许完美的转发工作

    “完美”转发意味着有效地转发参数,就像用户直接调用函数一样(减去省略,这被转发破坏)。用户可以传递三种类型的值:lvalues、xvalues和prvalues,并且接收位置可以采用三种方式获取值:按值、按(可能是常量)lvalue引用和按(可能是常量)rvalue引用

    考虑这一功能:

    template<class T>
    void Fwd(T &&v) { Call(std::forward<T>(v)); }
    
    模板
    void-Fwd(T&v){Call(std::forward(v));}
    
    按价值 如果
    Call
    按值获取其参数,则必须复制/移动该参数。哪一个取决于传入值是什么。如果传入值是左值,那么它必须复制左值。如果传入值是右值(统称为xvalues和prvalues),则它必须从右值移动

    如果使用左值调用
    Fwd
    ,C++的类型推断规则意味着
    T
    将被推断为
    type&
    ,其中
    type
    是左值的类型。显然,如果左值是
    const
    ,它将被推断为
    const-Type&
    。引用折叠规则意味着
    Type&&&
    成为
    v
    Type&
    ,一个左值引用。这正是我们需要调用的
    call
    。用左值引用调用它将强制复制,就像我们直接调用它一样

    如果使用右值调用
    Fwd
    (即:a
    Type
    临时表达式或某些
    Type&
    表达式),则
    T
    将被推断为
    Type
    。引用折叠规则为我们提供了
    类型&&
    ,这会引发移动/复制,这几乎完全就像我们直接调用它一样(减去省略)

    通过左值引用 如果
    Call
    通过左值引用获取其值,那么它应该仅在用户使用左值参数时才可调用。如果它是常量左值引用,那么它可以被任何东西调用(左值、xvalue、prvalue)

    如果您使用左值调用
    Fwd
    ,我们再次得到
    Type&
    作为
    v
    的类型。这将绑定到非常量左值引用。如果我们用常量左值调用它,我们会得到
    常量类型&
    ,它只会绑定到
    调用
    中的常量左值引用参数

    如果您使用x值调用
    Fwd
    ,我们将再次得到
    Type&
    作为
    v
    的类型。这将不允许调用采用非常量左值的函数,因为xvalue不能绑定到非常量左值引用。它可以绑定到常量左值引用,因此如果
    Call
    使用
    const&
    ,我们可以使用xvalue调用
    Fwd

    如果您使用prvalue调用
    Fwd
    ,我们再次得到
    类型&&
    ,因此一切都像以前一样工作。您不能将临时值传递给采用非常量左值的函数,因此我们的转发函数在尝试这样做时同样会阻塞

    通过右值引用 如果
    Call
    通过右值引用获取其值,则仅当用户使用xvalue或右值参数时才应可调用它

    如果您使用左值调用
    Fwd
    ,我们将得到
    类型&
    。这不会绑定到右值引用参数,因此会导致编译错误。
    常量类型&
    也不会绑定到右值引用