简体   繁体   English

我为什么要使用std :: forward?

[英]Why should I use std::forward?

In the code below, why should I use std::forward when passing around arguments? 在下面的代码中,为什么我在传递参数时使用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;
}

The code with or without std::forward doesn't show any copy/move around. 带或不带std::forward的代码不会显示任何副本/移动。

There are a number of good posts on what std::forward does and how it works (such as here and here ). 关于std::forward做什么以及如何工作(例如这里这里 )有很多好的帖子。

In a nutshell, it preserves the value category of its argument . 简而言之, 它保留了其参数的值类别 Perfect forwarding is there to ensure that the argument provided to a function is forwarded to another function (or used within the function) with the same value category (basically r-value vs. l-value) as originally provided . 完美转发是为了确保提供给函数的参数被转发到另一个函数(或在函数内使用),其具有与最初提供的相同的值类别(基本上是r值与l值)。 It is typically used with template functions where reference collapsing may have taken place (involving universal/forwarding references). 它通常与模板函数一起使用,其中可能发生了引用折叠 (涉及通用/转发引用)。

Consider the code sample below. 考虑下面的代码示例。 Removing the std::forward would print out requires lvalue and adding the std::forward prints out requires rvalue . 删除std::forward将打印出requires lvalue并添加std::forward打印输出requires rvalue The func is overloaded based on whether it is an rvalue or an lvalue. func根据它是rvalue还是左值来重载。 Calling it without the std::forward calls the incorrect overload. 在没有std::forward情况下调用它会调用不正确的重载。 The std::forward is required in this case as pass is called with an rvalue. 在这种情况下需要std::forward ,因为使用rvalue调用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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM