c++中函数形参中的右值引用

C++, rvalue references in function parameters

本文关键字:引用 形参 函数 c++      更新时间:2023-10-16

我正在努力理解rvalue参考。我已经看到它们是如何在构造函数中使用的,像std::movestd::forward这样的东西,但我仍然不明白为什么这不起作用:

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

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

为什么它与函数模板版本一起工作?

就像@Peter说的,T的类型被推断为string&, c++的引用崩溃规则说:

T&,⇒T&//from c++ 98
T&和;,⇒T&//新增c++ 0x
T&,,⇒T&//新增c++ 0x
T&和;,,⇒T&和;//新增c++ 0x

所以func的实例化实际上是:

void func(string& str)

它成功了

除了@ songyuananyao的回答之外,还有一些正式的解释:

N4296::14.8.2.1 [temp.deduct.call]:

通过比较每个函数来推导模板实参模板参数类型(称其为P)与类型相对应如下所述,调用的实参(称之为A)

N4296::14.8.2.1/3 [temp.deduct.call]:

一个转发引用对cv不限定模板形参的右值引用。如果P是a转发引用和参数是一个左值,类型为" lvalue "引用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&&)

因为在模板内部&&有不同的含义,所以它被称为通用引用

具有&&形参(通用引用)的模板函数意味着该形参可以用作引用或右值引用。

在你的例子中,模板被推断为string&,这就是它工作的原因。

要使用原始函数,您必须这样做:

void func(string&& str)
{
    cout << str << endl;
}
int main(int argc, char* argv[])
{
    string s("string");
    func(std::move(s)); // move the string
    func(std::string("string")); // this is an rvalue and it is fine
}

关于通用引用的完整解释可以在这里找到:https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers