析构函数和智能指针

本文针对析构做一个知识面的深度整理:C++面试真题!如何实现一个类,在父类没有虚析构函数的情况下,通过父类指针析构子类对象?

C++析构函数原理:

  1. 如果基类析构是非虚函数,当删除基类指针的时候,只会调用基类自己的析构函数
  2. 如果基类析构是虚函数,当删除基类指针的时候,会先调用子类析构,然后调用基类析构。
问题一:基类是非虚析构,删除基类指针。输出什么
class CA
{
public:
	~CA() { printf("~CA\r\n"); }
};

class CB :public CA 
{
public:
	~CB() { printf("~CB\r\n"); }
};

int main()
{
	CA* pCa = new CB;
	delete pCa;
}

输出结果:

~CA

因为基类是非虚析构,删除基类指针不会调用子类析构。

问题二:如果使用智能指针输出什么
std::shared_ptr<CA> ptrCb = std::make_shared<CB>();

输出结果:

~CB
~CA

和虚析构表现一样。会触发子类虚构。但是CA明显是非虚析构,不存在虚表。

问题三:为什么智能指针可以调用子类析构函数?

关于非析构函数的理论肯定不会有问题,那么真相只有一个:智能指针内部保存了new 对象的类型。

下面将模拟一段保存new 对象类型的方法。
方法一:

class manager
{
public:
	virtual ~manager() {}
};

template <class T>
class manager_ptr:public manager
{
public:
	manager_ptr(T p) : ptr(p) {}
	~manager_ptr() 
	{
		delete ptr;
	}
private:
	T ptr;
};

template <class T>
class _shared_ptr
{
public:
	template<class Y>
	_shared_ptr(Y* p) { ptr_manager = new manager_ptr<Y*>(p); }
	~_shared_ptr() 
	{ 
		delete ptr_manager;
	}
private:
	manager* ptr_manager;
};

manager_ptr的模板T保存了,new 对象的类型。所以delete的时候实际是删除的CB对象,即:delete pCB

方法二:

template <typename T>
class MySharedV2
{
public:
    template <typename T2>
    MySharedV2(T2 *p)
    {
        data_ = p;
        deleter_ = [p](){ delete p;};
    }
    ~MySharedV2()
    {
        deleter_();
    }
    T* operator->()
    {
        return data_;
    }
private:
    std::function<void()> deleter_;
    T* data_ = nullptr;
};

通过lambda表达式保存new 的对象类型。当析构的时候正确释放。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值