You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么‘推导this’模板与右值/左值重载的执行结果不同?

问题分析与解答

原代码逻辑回顾

原版本中A的prop方法通过重载左值/右值引用限定符,返回的是对象自身的引用:

  • 左值调用prop时,返回A&(绑定原对象)
  • 右值调用prop时,返回A&&(绑定原临时对象)

所以aa.prop(33).prop(4)的执行流程是:

  1. 左值aa调用prop(33),修改aa.pp为33,返回aa的左值引用
  2. 这个左值引用再调用prop(4),修改aa.pp为4,返回aa的左值引用
  3. 最终传给B的是左值aa,触发拷贝构造函数,同时aa.pp最终是4,符合预期。

疑问1:为什么修改版本会调用移动构造函数?

修改后的prop方法使用了推导this,但核心差异是返回类型从引用变成了值类型A:

template <typename self> A prop(this self &&me, int nn) {
  me.pp=nn;
  return me;
}

执行流程变为:

  1. 左值aa调用prop(33):self被推导为A&,me是aa的左值引用,修改aa.pp为33后,返回me的拷贝(因为返回类型是A,不是引用),得到一个临时对象(右值)。
  2. 这个临时右值调用prop(4):self被推导为A,me是临时对象的右值引用,修改临时对象的pp为4后,返回me的移动构造副本(因为me是右值,返回值类型是A,会触发移动语义),得到另一个临时右值。
  3. 最终传给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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 23:42:34