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

销毁对象后使用其引用:为何成员函数仍可正常调用?

为什么销毁后的对象成员函数还能正常调用?

这是典型的未定义行为场景——你的代码已经违反了C++的规则,只是刚好没触发崩溃而已,咱们一步步拆解来理解:

先定位代码的核心问题

在createA()函数里,局部对象A b的作用域仅限于内部的代码块{}。当这个代码块执行结束时,b会被自动销毁(也就是你看到输出里的des),但你却返回了它的引用*a(a指向的就是b的地址)。这就导致main()里的A &b变成了悬挂引用——它指向的对象已经彻底不存在了。

为什么b.f()还能正常执行?

关键在于你的f()成员函数完全没有访问对象的成员变量。

对于非虚成员函数,C++编译器的调用逻辑是这样的:

  • 调用obj.f()时,编译器会把它转换成类似A::f(&obj)的形式,把对象的地址作为隐含的this指针传递给函数。
  • 你的f()只是输出固定字符串,完全不需要使用this指针去读取对象的任何状态。所以哪怕this指向的是一块已经被释放的内存,只要这块内存还没被其他数据覆盖,函数依然能正常执行——因为它不需要依赖对象的任何成员数据。

如果把f()改成下面这样,你大概率会看到崩溃或者乱码:

// 先给类A加一个成员变量x
int x = 10;
void f() { 
    cout << "bla: " << x << endl; 
}

这时候函数需要访问对象的成员,就会去读取this指向的无效内存,立刻触发错误。

关于未定义行为的重要提醒

一定要记住:未定义行为不代表一定会崩溃,C++标准对这种情况没有任何保证。你的代码在当前编译器/环境下看起来正常,换个编译器、换个系统,或者只是代码稍微调整一下,就可能出现崩溃、输出乱码,甚至更诡异的问题。

修正方案推荐

有两种常见的正确做法:

  1. 返回对象值而非引用:函数会返回一个新的对象(调用拷贝构造函数),完全避免悬挂问题:
    A createA()
    {
        A b;
        return b;
    }
    
  2. 用智能指针管理动态对象:避免手动管理内存的麻烦,同时保证对象生命周期可控:
    #include <memory>
    std::unique_ptr<A> createA()
    {
        return std::make_unique<A>();
    }
    

你的程序输出:

con
des
0058FE0B
0058FE0B
bla
Press any key to continue . . .

两次输出的地址相同,是因为那块内存还没被系统重新分配,所以悬挂引用的地址看起来和原对象一致,但内存里的对象已经不存在了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:12:29