C++ C++;,函数参数中的右值引用
我试图理解C++ C++;,函数参数中的右值引用,c++,c++11,templates,rvalue-reference,C++,C++11,Templates,Rvalue Reference,我试图理解rvalue引用。我已经看到了它们是如何在构造函数中使用的,比如std::move和std::forward,但我仍然不明白为什么这不起作用: void func(string&& str) { cout << str << endl; } int main(int argc, char* argv[]) { string s("string"); func(s); } void func(字符串和str) { 如彼得所
rvalue
引用。我已经看到了它们是如何在构造函数中使用的,比如std::move
和std::forward
,但我仍然不明白为什么这不起作用:
void func(string&& str)
{
cout << str << endl;
}
int main(int argc, char* argv[])
{
string s("string");
func(s);
}
void func(字符串和str)
{
如彼得所说,<代码> t>代码>的类型被推断为String和,C++的引用崩溃规则表示:
T&⇒ T&//来自C++98
T&&⇒ T&//C++0x的新特性
T&&⇒ T&//C++0x的新特性
T&&&&&⇒ T&&//C++0x的新特性
所以func
的实例化实际上是:
void func(string& str)
它是有效的。除了@songyuanyao的答案之外,还有一些正式的解释:
N4296::14.8.2.1[临时扣减呼叫]
:
模板参数推导是通过比较每个函数来完成的
模板参数类型(称为P)与对应的
调用的参数(称为A),如下所述
N4296::14.8.2.1/3[临时扣减呼叫]
:
转发引用是
对cv非限定模板参数的右值引用
转发引用和参数为左值,类型为“左值”
在类型扣减中,使用“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&&)
模板int f(T&&heisenreference);
模板int g(常数T&&);
int i;
int n1=f(i);//调用f(int&)
int n2=f(0);//调用f(int&&)
int n3=g(i);//错误:将调用g(const int&)
这正是您的情况。因为模板内部的&&
具有不同的含义,所以它被称为通用参考
带有&&
参数(非个人参考)的模板函数意味着参数可以用作参考或右值参考
在您的例子中,模板被推断为字符串&
,这就是它工作的原因
要使用原始函数,必须执行以下操作:
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
}
void func(字符串和str)
{
cout后一种版本之所以有效,是因为当函数参数类型的形式为T&&其中T是模板参数,且函数参数是类型a的左值时,类型a&用于模板参数推断,因此将T
推断为string&
”如果希望前者起作用,请使用std::move
。这是模板推断的一种特殊情况,此处(并且仅在此处),可以将T
推断为引用类型。通常在模板类型推断中T
仅被推断为非引用。可能的
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
}