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

同一Lambda的不同定义为何导致C++执行结果差异?

为什么两种Lambda写法会导致不同的输出结果?

这是个很有意思的问题,核心差异在于**getNum的实际类型以及传递给tester时的行为**,咱们一步步拆解:

第一种情况:使用mylambda函数返回std::function

int main() {
    auto getNum = mylambda(1);
    tester(getNum);
    tester(getNum);
}

这里mylambda的返回值明确是std::function<int(void)>,所以getNum的类型就是std::function<int(void)。当你把getNum传给tester时,传递的是这个std::function对象的引用——也就是说两次tester调用共享同一个std::function实例,而这个实例内部持有的是同一个带mutable的lambda对象。

第一次tester调用时,lambda的starter从1开始递增,输出2到11;第二次调用时,starter已经是11了,继续递增输出12到21,所以最终结果是2到21的连续数字。

第二种情况:直接使用立即调用的Lambda返回Lambda

int main() {
    auto getNum = ([](int starter) { return [starter]() mutable { return ++starter; }; })(1);
    tester(getNum);
    tester(getNum);
}

这里的关键是:getNum的类型不是std::function,而是那个内部返回的、带mutable的lambda的具体类型(编译器生成的匿名闭包类型)。

当你把getNum传给tester时,因为tester的参数是const std::function<int(void)>&,编译器会每次都创建一个新的std::function实例,并且把getNum(也就是那个lambda)拷贝到这个新的std::function里。

这意味着两次tester调用使用的是两个完全独立的lambda副本:第一次调用时,副本的starter从1递增到11,输出2到11;第二次调用时,新的副本的starter又回到了1,再次输出2到11,所以结果是重复的2到11。

总结一下差异点

  • 第一种情况:getNum是std::function,两次tester共享同一个lambda实例,状态持续累加。
  • 第二种情况:getNum是原始lambda类型,每次传递给tester都会触发std::function的构造,拷贝出独立的lambda实例,状态无法共享。

如果想让第二种情况和第一种行为一致,你可以显式把getNum声明为std::function<int(void)>,比如:

std::function<int(void)> getNum = ([](int starter) { return [starter]() mutable { return ++starter; }; })(1);

这样getNum就是std::function类型,两次传递给tester时共享同一个实例,状态就会持续递增了。

内容的提问来源于stack exchange,提问作者Marco Luzzara

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:31:29