我写了这段代码:
#include <iostream>
void test(std::string && x) {
std::cout << "test: 1" << std::endl;
}
void test(const std::string & x) {
std::cout << "test: 2" << std::endl;
}
template<typename T>
void test2(T&& x) {
std::cout << "test2: 1" << std::endl;
}
template<typename T>
void test2(const T & x) {
std::cout << "test2: 2" << std::endl;
}
int main()
{
std::string x = "aaa";
std::string & y = x;
test(y);
test2(y);
return 0;
}
它有4个功能,两个名为
test
和两个test2
。 test2
由模板选择参数,test
静态。两种类型都有一种用于 const T & x
的重载和一种用于 T && x
的重载。但是如果我用T &
称呼它们,就会调用不同的类型。上面代码的结果是:
test: 2
test2: 1
如何,更重要的是,为什么会发生这种情况?
粗略地说,编译器更喜欢涉及“更简单”类型转换的函数重载。
由于无法将左值引用转换为右值引用,因此函数
void test(std::string &&x);
根本无法调用,但是从std::string&
到const std::string&
的转换是可以的。这就是为什么你在调用test
时得到“2”的原因。
模板案例不同,因为它也涉及到类型推导。
T&& x
是一个“通用引用”,它可以绑定任何东西,所以它不涉及任何类型转换。即当推导T
时,函数test2(T &&x)
变为test2(std::string &x)
,完美匹配并且不需要类型转换。
另一方面,
test2(const T& x)
变成test2(const std::string &x)
,需要1次类型转换,所以不如第一次重载有利。