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

C++中Lambda捕获类对象引用后,超出作用域为何仍正常输出?

为什么引用已销毁对象的Lambda调用没有崩溃?

先看你写的C++代码:

class sample1
{
    public:
    std::function<void()> p1;
    void configure(std::function<void()> TCallbackFn)
    {
        p1 = TCallbackFn;
    }
};

class test
{
    public:
    int a;
    test(int a) : a(a)
    {
       
    }
    ~test()
    {
        
    }
    void print() const
    {
        cout<<"Hello "<<a;
    }
};

int main()
{
    sample1 obj;
    {
        test t(4);
        obj.configure([&]()
        {
            t.print();
        });   
    }
    obj.p1();
}

这不是编译器优化导致的,而是未定义行为的一种巧合表现。

当局部作用域结束后,test对象t的内存会被标记为可回收,但操作系统或程序运行时并不会立刻清空或覆盖这块内存的内容。你的Lambda捕获的是t的引用,调用obj.p1()时,刚好这块内存还没被其他代码占用改写,所以访问a时读出了原来的4,就输出了"Hello 4"。

未定义行为的结果是完全不可预测的:如果在t销毁后、调用obj.p1()前,有其他代码分配并使用了这块内存,那你可能会看到垃圾值,甚至程序直接崩溃。编译器没有特意保留已销毁对象的内存内容,这只是刚好没被覆盖而已。

用伪代码模拟这个内存过程:

// 模拟内存状态变化
main() {
    为obj分配内存;
    {
        在栈上分配内存给t,地址假设为0x100,其中a的值设为4;
        将捕获0x100地址引用的Lambda赋值给obj.p1;
        // t离开作用域:标记0x100地址的内存为可用,但内存里的4还没被改写
    }
    // 此时0x100地址的内存未被其他操作占用
    调用obj.p1() → 访问0x100地址里的a,读出4,输出Hello 4;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 14:25:25