【问题标题】:C++, rvalue references in function parametersC++,函数参数中的右值引用
【发布时间】:2015-08-01 03:00:10
【问题描述】:

我正在尝试理解 rvalue 引用。我已经看到它们是如何在构造函数中使用的,例如 std::movestd::forward,但我仍然不明白为什么这不起作用:

void func(string&& str)
{
    cout << str << endl;
}
int main(int argc, char* argv[])
{
    string s("string");
    func(s);
}

确实如此:

template<typename T>
void func(T&& str)
{
    cout << str << endl;
}
int main(int argc, char* argv[])
{
    string s("string");
    func(s);
}

为什么它适用于函数模板版本?

【问题讨论】:

  • 后一个版本有效,因为T 被推断为string&amp;。 “当函数参数类型为 T&& 形式时,其中 T 是模板参数,而函数参数是类型 A 的左值,则类型 A& 用于模板参数推导。”如果您希望前者工作,请使用 std::move
  • 这是模板推导的一个特例,这里(也只有这里AFAIK),T可以推导为引用类型。通常在模板类型推导中T 只推导为非引用。

标签: c++ c++11 templates rvalue-reference


【解决方案1】:

就像@Peter 说的,T 的类型推导出为string&amp;,C++ 的引用折叠规则说:

T& & ⇒ T& // 来自 C++98
T&& & ⇒ T& // C++0x 的新功能
T& && ⇒ T& // C++0x 的新功能
T&& && ⇒ T&& // C++0x 的新特性

所以func的实例化其实是:

void func(string& str)

而且它有效。

【讨论】:

    【解决方案2】:

    除了@songyuanyao的回答之外的一些正式解释:

    N4296::14.8.2.1 [temp.deduct.call]:

    模板参数推导是通过比较每个函数来完成的 模板参数类型(称它为 P)与对应的类型 调用的参数(称为 A),如下所述。

    N4296::14.8.2.1/3 [temp.deduct.call]:

    一个转发参考对 cv 非限定模板参数的右值引用。如果 P 是一个 转发引用并且参数是一个左值,类型为“左值 引用 A” 代替 A 用于类型推导。

    该标准还提供了以下示例:

    template <class T> int f(T&& heisenreference);
    template <class T> int g(const T&&);
    int i;
    int n1 = f(i); // calls f<int&>(int&)
    int n2 = f(0); // calls f<int>(int&&)
    int n3 = g(i); // error: would call g<int>(const int&&)
    

    这正是你的情况。

    【讨论】:

      【解决方案3】:

      因为模板内部&amp;&amp;有不同的含义,所以称为通用引用

      带有&amp;&amp; 参数的模板函数(通用引用)意味着该参数可以用作引用或右值引用。

      在您的情况下,模板被推断为string&amp;,这就是它起作用的原因。

      要使用原始函数,您必须这样做:

      void func(string&& str)
      {
          cout << str << endl;
      }
      int main(int argc, char* argv[])
      {
          string s("string");
          func(std::move(s)); // move the string
          func(std::string("string")); // this is an rvalue and it is fine
      }
      

      可以在此处找到有关通用引用的完整说明: https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-07-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-12-03
        • 2019-11-04
        • 2021-05-23
        相关资源
        最近更新 更多