我们知道,shared_ptr是通过引用计数的方式来管理资源,那么现在的问题是,这个计数对象(counter)什么时候构造,什么时候释放?
先说构造的问题,逻辑上,计数对象应该是和资源的生命期是一致的,但是同时计数对象又和资源是分离的,资源并不知道计数对象的存在,因此不大可能是对象构造的时候去构造计数对象。 然而shared_ptr对象本身是离不开计数对象的,因此很容易想到是在shared_ptr对象本身构造的时候创建。直接看源码:
可以看到,确实是在构造的时候new了一个_Ref_count对象。 既然这个_Ref_count对象是new出来,那么什么时候释放呢?可能第一反应是资源释放的时候,即引用计数为0时。但是考虑std::weak_ptr,我们先看cppreference对std::weak_ptr的定义:
std::weak_ptr is a smart pointer that holds a non-owning ("weak") reference to an object that is managed by std::shared_ptr. It must be converted to std::shared_ptr in order to access the referenced object.std::weak_ptr models temporary ownership: when an object needs to be accessed only if it exists, and it may be deleted at any time by someone else, std::weak_ptr is used to track the object, and it is converted to std::shared_ptr to assume temporary ownership. If the original std::shared_ptr is destroyed at this time, the object's lifetime is extended until the temporary std::shared_ptr is destroyed as well.In addition, std::weak_ptr is used to break circular references of std::shared_ptr.
既然std::weak_ptr能够提升为std::shared_ptr,那么可以确定std::weak_ptr和std::shared_ptr共用一个RefCount。那么当资源已经释放时,即所有的std::shared_ptr对象都析构了,如果此时释放RefCount对象,那通过weak_ptr也拿不到资源的使用情况了,这显然是不对的。那么RefCount到底是什么时候释放的呢,答案是这个RefCount对象有两个引用计数,一个shared_ptr的计数,一个weak_ptr的计数。当shared_ptr的引用计数为0时,释放资源,当shared_ptr和weak_ptr的计数都为0,才释放RefCount对象。
_Decref()即为shared_ptr析构时调用,_Decwref()为weak_ptr析构时调用所以结论是:counter对象在shared_ptr对象构造的时候构造,在weak_ptr的引用计数为0时释放。
网友评论