请参阅下面的代码段(注意s是带char而不是string的数组):
#include <string>
#include <iostream>
#include <utility>
void func(std::string & s, char a) {
std::cout << "here1" << std::endl;
// ...
}
void func(std::string && s, char a) {
std::cout << "here2" << std::endl;
// ...
}
template <class T>
void foo(T && s) {
std::cout << "foo2" << std::endl;
func(s, ':');
//func(std::forward<T>(s), ':');
}
int main(int agrc, char *argv[])
{
//std::string s("a:b:c:d");
char s[8] = "abcdefg";
foo(std::move(s));
std::string s2("abcd")
foo(s2);
return 0;
}
如果我使用func(s, ':')
替换std::forward
,则没有区别,在这种情况下,foo函数将执行完美转发而不使用std::forward
。
在C ++ 11中,对std::forward
的'完美转发'是否有误解?
答案 0 :(得分:5)
它有所不同。在您的情况下,func(s, ':')
只会调用引用func
的{{1}}重载。
问题在于命名变量和参数本身就是左值,这也是std::string
首先存在的原因。
在您的示例中,即使您不使用std::forward
,也会为第一次调用foo
选择正确的重载。这只是因为您实际上使用std::forward
参数调用foo
,该参数用于隐式构造char[]
的临时值。
答案 1 :(得分:1)
让我们考虑第一个案例foo(std::move(s))
。在foo
内,s
将绑定到右值。但由于它有一个名称(s
),它不再是右值。因此,当您将s
传递给func
时,就像将左值传递给它一样 - 它会触发here1
版本。但是,如果您通过s
传递std::forward
,它将再次成为右值。
在第二种情况下,当输入foo时,s
是左值引用,因此无论是直接传递还是通过std::forward
传递它都不会改变任何内容。您需要使用std::move
再次从s
中获取rvalue。