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
相关产品推荐
相关产品推荐

