C++,函数参数中的右值引用

Car*_*sHD 15 c++ templates rvalue-reference c++11

我正在努力理解rvalue参考文献.我看到他们是如何在构造函数中使用,之类的东西std::movestd::forward,但我还是不明白为什么这不起作用:

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

这样做:

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

为什么它与函数模板版本一起使用?

son*_*yao 15

就像@Peter所说的T那样string&,推断出类型,并且C++的引用折叠规则说:

T
&&⇒T &//来自C++ 98 T&&&⇒T&// new for C++ 0x
T&&&⇒T&// new for C++ 0x
T&&&&⇒T&& // new for C++ 0x

所以func实例化实际上是:

void func(string& str)
Run Code Online (Sandbox Code Playgroud)

它有效.


小智 6

除了@ 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&&)
Run Code Online (Sandbox Code Playgroud)

这正是你的情况.