为什么‘推导this’模板与右值/左值重载的执行结果不同?
问题分析与解答
原代码逻辑回顾
原版本中A的prop方法通过重载左值/右值引用限定符,返回的是对象自身的引用:
- 左值调用
prop时,返回A&(绑定原对象) - 右值调用
prop时,返回A&&(绑定原临时对象)
所以aa.prop(33).prop(4)的执行流程是:
- 左值
aa调用prop(33),修改aa.pp为33,返回aa的左值引用 - 这个左值引用再调用
prop(4),修改aa.pp为4,返回aa的左值引用 - 最终传给
B的是左值aa,触发拷贝构造函数,同时aa.pp最终是4,符合预期。
疑问1:为什么修改版本会调用移动构造函数?
修改后的prop方法使用了推导this,但核心差异是返回类型从引用变成了值类型A:
template <typename self> A prop(this self &&me, int nn) { me.pp=nn; return me; }
执行流程变为:
- 左值
aa调用prop(33):self被推导为A&,me是aa的左值引用,修改aa.pp为33后,返回me的拷贝(因为返回类型是A,不是引用),得到一个临时对象(右值)。 - 这个临时右值调用
prop(4):self被推导为A,me是临时对象的右值引用,修改临时对象的pp为4后,返回me的移动构造副本(因为me是右值,返回值类型是A,会触发移动语义),得到另一个临时右值。 - 最终传给
B的是这个临时右值,符合B(A&&)的参数匹配,因此调用移动构造函数。
疑问2:为什么aa.pp的值是33而非4?
因为修改后的prop返回的是对象副本,不是原对象的引用:
- 第一次调用
aa.prop(33):确实修改了原对象aa的pp为33,但返回的是aa的拷贝(临时对象)。 - 第二次调用
prop(4):操作的是第一次返回的临时对象,修改的是这个副本的pp为4,和原对象aa没有任何关系。 - 原对象
aa只在第一次调用时被修改为33,后续操作都在副本上执行,所以最终aa.pp的值是33。
内容的提问来源于stack exchange,提问作者John Gordon
相关产品推荐
相关产品推荐

