关于虚析构函数和shared_ptr的错误记录

本文探讨了在使用C++的多态和shared_ptr时,遇到的虚析构函数未被调用问题,并揭示了解决方案:通过声明基类析构函数为virtual或直接传入基类指针。深入剖析了编译器行为和底层实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关于虚析构函数和shared_ptr的错误记录

起因

最近在写那个串口调试工具的替代品. 然后有个地方,感觉很麻烦,想了几天,决定用cpp的多态来解决.说到cpp的多态,就没法脱离引用或者是指针,我会用的就是shared_ptr了,自动计数指针!

经过

然后我就把它两结合了起来,发现结果是错误的,然后就开始调试,试了一段时间,发现析构函数根本就没有被调用.我将代码进行抽象如下:

#include <memory>

class Base{
//is the public: necessary
public:
	//(1)
	//virtual Base() {}
};

class Sub: public Base{
	public:
	~Sub() {
		//do something
	}
}

void foo() {
	Base *b=new Sub();
	shared_ptr<Base> pb(b);
	//(2)
	//shared_ptr<Base> pb(new Sub());
}
int main() {
	foo();
	return 0;
}

几次实验之后发现有两种解决方法:

  1. 在Base类中声明析构函数为virtual,即注释(1)内容
  2. 直接将new出的指针传入shared_ptr<Base>的构造函数

其中第一种方法,本人可以理解,应为基类的指针析构时没有调用动态类型的析构函数.但第二种就不理解了,难道传入的其实不是Base *类型?

结果

之后上Compiler Explorer上查了下汇编,做了下差分,果不其然:

%PATH%>diff a b
1,7d0
< Sub::~Sub() [base object destructor]:
<         push    rbp
<         mov     rbp, rsp
<         mov     QWORD PTR [rbp-8], rdi
<         nop
<         pop     rbp
<         ret
11c4
<         sub     rsp, 16
---
>         sub     rsp, 32
14,15c7,9
<         mov     rdx, rax
<         lea     rax, [rbp-16]
---
>         mov     QWORD PTR [rbp-8], rax
>         mov     rdx, QWORD PTR [rbp-8]
>         lea     rax, [rbp-32]
18,19c12,13
<         call    std::shared_ptr<Base>::shared_ptr<Sub, void>(Sub*)
<         lea     rax, [rbp-16]
---
>         call    std::shared_ptr<Base>::shared_ptr<Base, void>(Base*)
>         lea     rax, [rbp-32]
...

至于std::shared_ptr<Base>::shared_ptr<Sub,void>到底是什么,就让它成为又一个

未解之谜

吧 xp

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值