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

C++显式调用析构函数的对象销毁及重复析构问题咨询

显式调用析构函数时对象是否会被销毁?

示例代码

#include <iostream>
#include <memory>

class A
{
public:
    A()
    {
        std::cout << "A()\n";
    }

    ~A()
    {
        std::cout << "~A()\n";
    }

    int a = 100;
};

class B
{
public:
    B()
    {
        ptr.reset(new A());
        std::cout << "B()\n";
        std::cout << "pointer value" << ptr.get() << std::endl;
        std::cout << ptr->a << std::endl;
    }

    ~B()
    {
        std::cout << "~B()\n";
    }

    void print()
    {
        std::cout << "print() " << a << b << "\n";
        std::cout << "pointer value" << ptr.get() << std::endl;
        std::cout << ptr->a << std::endl;
    }
private:
    std::unique_ptr<A> ptr;
    int a = 10;
    int b = 5;
};

int main()
{
    std::unique_ptr<B> p1(new B());   
    p1->~B();
    p1->print();
    return 0;
}

程序输出

A()
B()
pointer value010ECB60
100
~B()
~A()
print() 105
pointer value010ECB60
-572662307
~B()
~A()

疑问解答

1. 显式调用B的析构函数时,为何A的析构被调用但B的成员仍可访问?

  • 析构函数的核心作用是清理对象持有的资源,而非直接销毁对象本身的内存。B对象的内存由std::unique_ptr管理,只有当unique_ptr生命周期结束时才会释放这块内存。
  • B的析构函数会触发其成员std::unique_ptr<A> ptr的析构,unique_ptr的析构逻辑是自动调用所管理A对象的析构函数并释放A的内存,所以你会看到~A()被调用,此时ptr指向的是已释放的野指针,后续访问ptr->a得到的是垃圾值。
  • B的成员a和b是直接存储在B对象内存中的,显式调用析构函数不会回收B的内存,所以这两个成员的值暂时保留(但此时B对象已处于“析构后”状态,标准中访问这类对象属于未定义行为,值未改变只是当前环境的巧合)。

2. 程序崩溃是否因A对象被重复销毁导致?

是的,崩溃根源就是A对象被重复释放:

  • main函数结束时,std::unique_ptr<B> p1会自动执行delete操作,而delete会先调用B的析构函数,这是第二次调用B的析构。
  • 第二次调用B的析构时,成员ptr会再次被析构,而ptr指向的A对象已经在第一次显式调用B析构时被销毁并释放内存了,unique_ptr尝试再次释放这块已被回收的堆内存,触发了堆内存重复释放的错误,导致程序崩溃。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 22:55:27