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

C++ Lambda按引用捕获:成员变量何时及为何发生变更?

C++ Lambda按引用捕获的变量变更问题解析

先看你提供的示例代码:

#include <iostream>
#include <functional>
using namespace std;

function<int(int)> func1( int y ) {
    return [&]( int argument ) {
        return argument + y;
    };
}

function<int(int)> func2( int y ) {
    class Lambda { public:
            Lambda( int& data ) : m_data( data ) {
                cout << "ctor: " << m_data << endl;
            }
            int operator () ( int argument ) {
                cout << "data lambda: " << m_data << endl; // why and when does m_data change?
                cout << "argument lambda: " << argument << endl;
                return m_data + argument;
            }
        const int& m_data;
    };

    return Lambda( y );
}

int main() {
    // rewritten lambda
    auto lambda1 = func1( 1 );
    auto result1 = lambda1( 10 );
    cout << "lambda2( 10 ) = "  << result1 << endl;

    // C++ lambda
    auto lambda2 = func2( 1 );
    auto result2 = lambda2( 10 );
    cout << "lambda2( 10 ) = "  << result2 << endl;
}

运行输出:

lambda2( 10 ) = 20
ctor: 1
data lambda: 10
argument lambda: 10
lambda2( 10 ) = 20

核心问题解析

你疑惑的m_data从1变为10,本质是悬垂引用引发的未定义行为,具体原因如下:

  • 局部变量生命周期终止:func2的参数y是函数栈上的局部变量,当func2执行完成返回Lambda对象后,y的生命周期就结束了,对应的栈内存会被系统标记为可复用。而Lambda的成员m_data是一个引用,绑定的正是这个已经销毁的y。
  • 栈内存被复用覆盖:当你在main函数中调用lambda2(10)时,程序需要将参数10压入栈中,此时之前存放y的那块栈内存刚好被这个参数值覆盖,所以访问m_data时就读到了10。
  • func1的情况完全一致:func1返回的lambda同样按引用捕获了局部变量y,导致悬垂引用,执行lambda1(10)时的结果也是栈内存复用的巧合,并非预期行为。

正确做法

如果需要让lambda在函数外部正常工作,要么按值捕获局部变量(把[&]改成[=],或者显式[y]),要么确保被引用的变量生命周期长于lambda(比如使用全局变量、动态分配的内存,或者让变量存在于lambda的作用域之外)。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 02:31:08