在下面的代码中,为什么我在传递参数时使用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
的代码不会显示任何副本/移动。
答案 0 :(得分:8)
关于std::forward
做了什么以及它如何运作(例如here和here),有很多好文章。
简而言之,它保留了其参数的值类别。完美转发是为了确保提供给函数的参数被转发到另一个函数(或在函数内使用),其具有与originally provided相同的值类别(基本上是r值与l值)。它通常用于可能发生reference collapsing的模板函数(涉及通用/转发引用)。
考虑下面的代码示例。删除std::forward
会打印requires lvalue
并添加std::forward
打印出requires rvalue
。 func
根据它是右值还是左值而重载。在没有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;
}