C++运算符重载疑问:x=y+p为何未调用预期的operator=?求解决方案
问题分析与解决方案
为什么会出现不符合预期的调用顺序?
咱们一步步拆解x=y+p的执行逻辑就能明白:
- 首先执行
y+p:y是A类型,p是ACHAR*,刚好匹配你定义的(3)号operator+,返回一个临时的A对象。 - 接下来要把这个临时对象赋值给
x,但你的(2)号赋值运算符参数是A &a——这是个非const的左值引用,而临时对象属于右值,C++里右值是不能绑定到非const左值引用上的! - 编译器找不到直接匹配的赋值重载,就会开始寻找其他可行路径:它发现
A有个隐式转换运算符(4),能把临时A对象转成ACHAR*,这样就可以匹配到(1)号的operator=(const ACHAR*)了,于是就出现了你看到的(3)(4)(1)调用链。
核心问题就是:临时右值无法绑定到非const左值引用的参数,导致编译器走了类型转换的 fallback 路径。
如何修复这个问题?
有两种常用的解决方案,按需选择:
方案1:把赋值运算符(2)改成const左值引用(最推荐)
修改(2)的声明为:
A &operator=(const A &a);
const左值引用的特性就是既能绑定普通左值(比如y),也能绑定临时右值(y+p返回的对象)。这样编译器就会优先匹配这个重载,不会再去触发那个意外的类型转换了。而且从语义上来说,赋值操作本来就不应该修改被赋值的源对象,加上const是非常合理的设计。
方案2:添加右值引用版本的赋值运算符(C++11+)
如果你需要针对临时对象做优化(比如实现移动语义),可以额外加一个右值引用的赋值重载:
A &operator=(A &&a);
这样临时的A右值会直接匹配这个版本,同样能避免触发类型转换。不过如果只是解决当前的问题,方案1已经完全够用。
另外提个小建议:你的(4)号转换运算符是隐式的,这种隐式转换很容易引发各种意想不到的类型匹配问题。如果不是必须要隐式转换的话,建议改成显式转换(C++11及以后支持):
explicit operator ACHAR*();
这样编译器就不会自动触发这个转换,只有当你显式写static_cast<ACHAR*>(temp_A_obj)的时候才会生效,能从根源上减少这类意外。
内容的提问来源于stack exchange,提问作者Chezi
相关产品推荐
相关产品推荐

