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

C++模板中调用重载operator()无法修改类成员变量值

C++模板传值导致对象修改未生效的原因与解决方法

问题的核心原因是模板函数的参数采用了传值传递:

当你调用NodeWalk(obj)时,模板参数T action会创建一个Foo对象的副本。你在重载的operator()里修改的是这个副本的bar_成员,而非原对象obj的bar_。函数执行完毕后,副本被销毁,原对象的状态完全没有被改变,所以后续调用obj.GetBar()得到的还是初始值1。

具体流程拆解

  1. main中创建Foo obj,其bar_初始化为1;
  2. 调用NodeWalk(obj)时,参数action是obj的拷贝,此时存在两个独立的Foo对象:原对象obj和副本action;
  3. 在NodeWalk内调用action(),修改的是副本action的bar_,所以内部打印显示bar_ = 2;
  4. NodeWalk执行结束,副本action被销毁,回到main后访问原对象obj的bar_,值仍为初始的1。

解决方法

将模板函数的参数改为引用传递,这样就会直接操作原对象,而非创建副本。修改后的模板函数如下:

template <typename T>
int NodeWalk(T& action) {  // 将参数改为引用类型
  action();
  return 0;
}

修改后再运行代码,输出会变为:

print in the operator: bar_ = 2
print outside the operator: bar_ = 2

如果需要支持传入临时对象(比如NodeWalk(Foo())),可以使用万能引用配合std::forward实现完美转发,写法如下:

#include <utility>  // 需要包含头文件

template <typename T>
int NodeWalk(T&& action) {
  std::forward<T>(action)();
  return 0;
}

这种写法既支持左值(如原代码中的obj),也支持右值(临时对象),但对于你的当前场景,第一种普通引用的修改方式已经足够解决问题。

内容的提问来源于stack exchange,提问作者ada liu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 04:06:25