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

C++对象调用成员方法删除自身是否可行?代码行为解析

对象自销毁的行为疑问与分析

一、裸指针实现的崩溃原因

当类对象调用成员方法时,若方法内部销毁对象本身,裸指针实现会直接崩溃,核心原因是销毁对象后,方法返回时会访问已失效的指针上下文。

裸指针实现代码

class Foo
{
public:
    virtual void Run()
    {
        printf("Entering callback\n");
        RunSomeCallback();
        printf("We're back from callback\n");
    }
    virtual void RunSomeCallback() = 0;
    
    virtual ~Foo()
    {
        printf("We're Destroyed\n");
    }
};

Foo* f = nullptr;

void DestroyFoo();

class Bar : public Foo
{
public:
    virtual void RunSomeCallback()
    {
        printf("Inside callback\n");
        DestroyFoo();
    }
};


void DestroyFoo()
{
    printf("Deleting foo\n");
    delete f;
}
int main()
{
    f = new Bar();
    f->Run();
    return 0;
}

崩溃逻辑:

  • 调用f->Run()后进入Run方法,执行RunSomeCallback();
  • RunSomeCallback()内部调用DestroyFoo(),执行delete f释放对象内存,析构函数执行;
  • 当RunSomeCallback()返回时,程序试图回到Run方法继续执行剩余代码,但此时this指针已指向被释放的内存,访问该上下文属于未定义行为,直接触发崩溃。

二、shared_ptr实现的行为分析

改用std::shared_ptr后代码可运行,但这种行为仍属于未定义行为,只是巧合未触发崩溃。

shared_ptr实现代码

class Foo
{
public:
    virtual void Run()
    {
        printf("Entering callback\n");
        RunSomeCallback();
        printf("We're back from callback\n");
    }
    virtual void RunSomeCallback() = 0;
    
    virtual ~Foo()
    {
        printf("We're Destroyed\n");
    }
};

std::shared_ptr<Foo> f;

void DestroyFoo();

class Bar : public Foo
{
public:
    virtual void RunSomeCallback()
    {
        printf("Inside callback\n");
        DestroyFoo();
    }
};


void DestroyFoo()
{
    printf("Deleting foo\n");
    f = nullptr;
}
int main()
{
    f = std::make_shared<Bar>();
    f->Run();
    return 0;
}

实际打印顺序

Entering callback
Inside callback
Deleting foo
We're Destroyed
We're back from callback

行为解读

  • 执行f = nullptr时,shared_ptr引用计数降为0,触发对象析构;
  • 此时Run方法未执行完毕,但剩余代码仅为printf,未访问对象成员或调用虚函数,因此未触发崩溃;
  • 这只是偶然情况,标准未保证该行为的安全性。若Run剩余代码访问对象成员或调用虚函数,同样会触发未定义行为导致崩溃。

三、对象销毁时机的明确结论

对象的析构函数执行完成后,对象就已被彻底销毁,不存在“等到所有成员方法执行完成后才真正销毁”的情况。shared_ptr例子中析构函数先执行但代码仍能运行,只是因为剩余代码未触碰已销毁对象的资源,不代表该行为合法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 03:43:15