带符号与无符号右值引用函数重载:unsigned变量为何匹配int&&?
右值引用在函数重载中的匹配疑惑
测试代码
#include <iostream> using namespace std; void test(int && n) { cout << "in test int &&" << endl; } void test(unsigned int && n) { cout << "in test unsigned int &&" << endl; } int main() { unsigned int n = 5; test(std::move(n)); // ---> 1 test(n); // ---> 2 test(5); // ---> 3 return 0; }
运行输出
in test unsigned int && in test int && in test int &&
问题
其中输出第1行和第3行符合预期(默认int为带符号类型),但第2行调用test(n)时,n是unsigned int类型,预期会匹配test(unsigned int && n),实际却匹配了test(int && n),这是为什么?
解答
核心原因在于:你的两个重载函数都只接受右值引用参数,但n是一个左值。
直接调用test(n)时,编译器的匹配逻辑是这样的:
- 首先寻找能直接接受左值的重载——你这里没有定义任何左值引用版本的
test,所以这一步找不到匹配项。 - 接下来编译器会尝试通过隐式转换,把左值
n转成某个重载能接受的右值,再选择最优路径:- 要匹配
unsigned int &&,必须把左值unsigned int转成同类型的右值引用,但编译器不会自动做这件事——右值引用绑定左值必须显式用std::move或者强制转换,这是为了防止程序员不小心转移左值的所有权。 - 而
unsigned int类型的n可以隐式转换为signed int,编译器会生成一个signed int的临时对象(这是右值),然后绑定到int &&参数上。
- 要匹配
虽然这个转换会改变类型的符号属性,但因为没有其他可行的匹配选项,编译器只能选择这个路径,最终调用了test(int &&)。
如果想让test(n)匹配unsigned int &&的重载,要么显式添加std::move(n)(就像第1行那样),要么新增一个接受unsigned int &或const unsigned int &的重载——左值会优先匹配这个不需要类型转换的版本。
内容的提问来源于stack exchange,提问作者kadina
相关产品推荐
相关产品推荐

