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

关于虚析构函数和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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++中,函数可以返回一个shared_ptr对象。可以通过以下几种方式来返回shared_ptr对象: 1. 使用make_shared函数:可以使用std::make_shared函数来创建一个shared_ptr对象,并将其作为函数的返回值。例如: ```cpp std::shared_ptr<MyClass> createObject() { return std::make_shared<MyClass>("Hello", 3.14); } ``` 2. 使用new关键字:可以使用new关键字手动创建一个对象,并将其包装在shared_ptr中返回。例如: ```cpp std::shared_ptr<int> createInt() { return std::shared_ptr<int>(new int(1)); } ``` 3. 使用reset函数:可以先创建一个空的shared_ptr对象,然后使用reset函数将其重新指向一个新的对象。例如: ```cpp std::shared_ptr<int> createInt() { std::shared_ptr<int> ptr; ptr.reset(new int(1)); return ptr; } ``` 无论使用哪种方式,函数返回的shared_ptr对象都可以在函数外部进行使用和管理。 #### 引用[.reference_title] - *1* *3* [C++11 解决内存泄露问题的智能指针:shared_ptr、unique_ptr、weak_ptr](https://blog.csdn.net/weixin_44120785/article/details/128714630)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [智能指针shared_ptr、unique_ptr、weak_ptr](https://blog.csdn.net/weixin_44477424/article/details/125902769)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值