为何将右值绑定到const类型会使其成为左值?
问题:const修饰std::pair成员类型导致函数重载匹配差异
我这段代码运行后输出“lvalue”,但如果移除MyPair第一个类型的const修饰,会得到预期的“rvalue”。想了解const在此处起到了什么作用?
#include <iostream> #include <utility> #include <string> using MyPair = std::pair<const std::string, int>; void func(std::string&& str) { std::cout << "rvalue" << std::endl; } void func(const std::string& str) { std::cout << "lvalue" << std::endl; } template<typename T> void func_forward(T&& p) { func(std::forward<T>(p).first); } void test(MyPair&& p) { func_forward(std::move(p)); } int main() { test({"hello", 3}); return 0; }
问题解析
核心原因是C++中右值对象的成员访问值类别规则,const修饰直接改变了成员访问表达式的性质:
带const修饰的情况:
func_forward里std::forward<T>(p)返回的是MyPair&&类型的右值对象- 访问该右值的
first成员时,由于first的类型是const std::string,C++规定右值对象的const限定成员访问结果是左值 - 这个左值会匹配
func(const std::string&)重载,因此输出"lvalue"
移除const修饰的情况:
- 同样
std::forward<T>(p)返回MyPair&&右值对象 - 此时
first是std::string(非const),C++规定右值对象的非const成员访问结果是xvalue(属于右值范畴) - 这个右值会匹配
func(std::string&&)重载,因此输出"rvalue"
- 同样
关键规则总结
对右值对象的非静态数据成员访问:
- 非const成员:访问结果为xvalue(可移动右值),能绑定到右值引用
- const成员:访问结果为左值,只能绑定到const左值引用(因为const成员不可修改,编译器将其视为左值以保证安全)
内容的提问来源于stack exchange,提问作者armques
相关产品推荐
相关产品推荐

