所以我用C++11 写了一段代码
#include <iostream>
using namespace std;
void print (int &&a)
{
cout<<"rval ref";
}
void print (const int& a)
{
cout<<"const ref";
}
int main()
{
print(9);
}
代码的输出非常吸引人;rval引用";但如果我重写代码只是删除一个函数定义:
#include <iostream>
using namespace std;
void print (const int& a)
{
cout<<"const ref";
}
int main()
{
print(9);
}
我得到的输出是";const-ref";
编辑:如果我再次将代码重写为,这里还有一件事
#include <iostream>
using namespace std;
void print (int &&a)
{
cout<<"rval ref";
}
void print (const int&& a)
{
cout<<"const ref";
}
int main()
{
print(9);
}
仍在印刷";rval ref",请解释的逻辑
有人能解释一下为什么C++偏爱&;传递ravalue作为参数时超过const?##标题##
让我们逐个查看发生了什么:
情况1
这里我们考虑:
void print (int &&a)
{
cout<<"rval ref";
}
void print (const int& a)
{
cout<<"const ref";
}
int main()
{
print(9); //chooses print(int&&) version
}
这种情况1的行为可以从over.ics.rank中理解,它表示:
3.2如果,标准转换序列
S1
是比标准转换序列S2
更好的转换序列
S1
和S2
是引用绑定([dcl.init.ref](,两者都不引用在没有ref限定符的情况下声明的非静态成员函数的隐式对象参数,并且S1
将右值引用绑定到右值,S2
将左值引用绑定。
(强调矿(
这意味着在本例1中,与const int&
相比,具有int&&
的版本更可取。
情况2
这里我们考虑:
void print (const int& a)
{
cout<<"const ref";
}
int main()
{
print(9); //chooses the only viable and available option print(const int&)
}
在情况2中,由于允许对const
对象的左值引用绑定到右值,因此所提供的print(const int&)
是可行的,并且是唯一可用的,因此被选择。
情况3
这里我们考虑:
void print (int &&a)
{
cout<<"rval ref";
}
void print (const int&& a)
{
cout<<"const ref";
}
int main()
{
print(9);
}
现在,它选择第一个版本print(int&&)
,因为9
是int
prvalue而不是const int
prvalue。还要注意,对于const int
prvalue,其const
将在任何进一步分析之前被剥离,因此将选择第一个版本print(int&&)
。这是expr#6:中规定的
如果一个prvalue最初具有类型
cv T
,其中T
是cv不合格的非类、非数组类型,则在进行任何进一步分析之前,表达式的类型将调整为T
这意味着对于类类型const
prvalues,将选择具有print(const C&&)
的函数print
的第二个版本,这与内置类型int
不同,如下所示。
struct C
{
C()
{
std::cout<<"default ctor"<<std::endl;
}
};
void print (C &&a)
{
cout<<"rval ref";
}
void print (const C&& a)
{
cout<<"const ref";
}
const C func()
{
const C temp;
return temp;
}
int main()
{
print(func()); //prints const ref
}
对于类别类型C
,上述程序的输出为:
default ctor
const ref
从上面的例子中可以明显看出,对于类类型,将选择带有const C&&
的第二个打印版本。