【问题标题】:Why should I use std::forward?为什么我应该使用 std::forward?
【发布时间】:2014-12-20 10:48:03
【问题描述】:

在下面的代码中,为什么我应该在传递参数时使用std::forward

class Test {
  public:
  Test() {
      std::cout << "ctor" << std::endl;
  }
  Test(const Test&) {
      std::cout << "copy ctor" << std::endl;
  }
  Test(const Test&&) {
      std::cout << "move ctor" << std::endl;
  }
};

template<typename Arg>
void pass(Arg&& arg) {
    // use arg..
    return; 
}

template<typename Arg, typename ...Args>
void pass(Arg&& arg, Args&&... args)
{
    // use arg...
    return pass(args...); // why should I use std::forward<Arg>(args)... ?
}

int main(int argc, char** argv)
{
    pass(std::move<Test>(Test()));

    return 0;
}

带有或不带有std::forward 的代码不会显示任何复制/移动。

【问题讨论】:

标签: c++ c++11


【解决方案1】:

有很多关于std::forward 的作用和工作原理的好帖子(例如herehere)。

简而言之,它保留了其参数的值类别。完美转发是为了确保提供给函数的参数被转发到另一个函数(或在函数内使用),其值类别(基本上是 r 值与 l 值)与 originally provided 相同。它通常与可能发生reference collapsing 的模板函数一起使用(涉及通用/转发引用)。

考虑下面的代码示例。删除std::forward 将打印出requires lvalue,添加std::forward 将打印出requires rvaluefunc 根据它是右值还是左值而被重载。在没有std::forward 的情况下调用它会调用不正确的重载。在这种情况下,std::forward 是必需的,因为 pass 是用右值调用的。

#include <utility>
#include <iostream>
class Test {
  public:
  Test() {
      std::cout << "ctor" << std::endl;
  }
  Test(const Test&) {
      std::cout << "copy ctor" << std::endl;
  }
  Test(Test&&) {
      std::cout << "move ctor" << std::endl;
  }
};

void func(Test const&)
{
    std::cout << "requires lvalue" << std::endl;
}

void func(Test&&)
{
    std::cout << "requires rvalue" << std::endl;
}

template<typename Arg>
void pass(Arg&& arg) {
    // use arg here
    func(std::forward<Arg>(arg));
    return; 
}

template<typename Arg, typename ...Args>
void pass(Arg&& arg, Args&&... args)
{
    // use arg here
    return pass(std::forward<Args>(args)...);
}

int main(int, char**)
{
    pass(std::move<Test>(Test()));
    return 0;
}

【讨论】:

  • 为什么调用Test const& 版本会不正确?我的意思是:价格是多少?
  • @user3834459 取决于函数的作用。如果两个重载之间的功能需要(或针对)值类别进行优化,那么是的,否则可能不是。一般来说,给定这两个重载,假设存在一些差异,最好调用正确的版本。
  • 好的,知道了。谢谢!
猜你喜欢
  • 2015-09-24
  • 1970-01-01
  • 2017-11-05
  • 2019-04-14
  • 1970-01-01
  • 1970-01-01
  • 2014-06-12
  • 2016-11-15
  • 2011-07-03
相关资源
最近更新 更多