Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/128.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;,函数参数中的右值引用_C++_C++11_Templates_Rvalue Reference - Fatal编程技术网

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
}