一、C++析构函数的调用
在C++编程中,有两个很让人头痛的问题:一是忘记释放动态申 请的对象从而造成内存泄露(通过new生成的对象,需要调用delete才能释放内存);二是对象在一个地方释放后,又在别的地方被使用,从而引起内存访问错误(多个指针指向同一个对象,其中一个指针delete)。
#include <iostream>
using namespace std;
class A{
public :
A(){
cout << "无参构造函数被调用" << endl;
}
~A(){
cout << "析构函数被调用" << endl;
}
};
void test1(){
A testA; //对象建立
//方法结束时,由系统自动调用析构函数释放对象
}
void test2(){
A* pa = new A();
delete pa; //手动调用析构函数释放对象
}
void test3(){
A* pa = new A();
//方法结束时,系统不会自动调用析构函数释放对象,对象存在内存中
}
二、RefBase与sp、wp
1、RefBase介绍
RefBase是安卓CPP中所有对象的始祖,类似于JAVA中的Object对象。
在安卓中,RefBase结合sp(强指针)和wp(弱指针),实现了通过引用计数的方法来控制对象的生命周期的机制,解决对象的自动释放的问题。在C++编程中,有两个很让人头痛的问题:一是忘记释放动态申 请的对象从而造成内存泄露(通过new生成的对象,需要调用delete才能释放内存);二是对象在一个地方释放后,又在别的地方被使用,从而引起内存访问错误(多个指针指向同一个对象,其中一个指针delete)。在使用RefBase后,动态申请的内存将会被自动释放(有点类似Java的垃圾回收),不需要再使用delete来释放对象,也不需要考虑一个对 象是否已经在其它地方被释放了,从而使程序编写工作减轻不少,而程序的稳定性大大提高。
2、RefBase类结构
生成一个RefBase对象,会默认生成一个weakref_impl对,并且用指针mRefs指向此对象,weakref_impl类继承于weakref_type类,而weakref_type是RefBase的内部类,weakref_impl有一个mBase指针指向RefBase对象。关系如下图:
三个类的构造函数或定义:
RefBase::RefBase()
: mRefs(new weakref_impl(this))
{
}
//weakref_impl的定义
class RefBase::weakref_impl : public RefBase::weakref_type
{
public:
std::atomic<int32_t> mStrong;
std::atomic<int32_t> mWeak;
RefBase* const mBase;
std::atomic<int32_t> mFlags;
//weakref_impl的构造函数
weakref_impl(RefBase* base)
: mStrong(INITIAL_STRONG_VALUE)
, mWeak(0)
, mBase(base)
, mFlags(0)
, mStrongRefs(NULL)
, mWeakRefs(NULL)
, mTrackEnabled(!!DEBUG_REFS_ENABLED_BY_DEFAULT)
, mRetain(false)
{
}
class RefBase
{
public:
void incStrong(const void* id) const;
void decStrong(const void* id) const;
void forceIncStrong(const void* id) const;
//! DEBUGGING ONLY: Get current strong ref count.
int32_t getStrongCount() const;
//weakref_type定义
class weakref_type
{
public:
RefBase* refBase() const;
void incWeak(const void* id);
void decWeak(const void* id);
// acquires a strong reference if there is already one.
bool attemptIncStrong(const void* id);
// acquires a weak reference if there is already one.
// This is not always safe. see ProcessState.cpp and BpBinder.cpp
// for proper use.
bool attemptIncWeak(const void* id);
//! DEBUGGING ONLY: Get current weak ref count.
int32_t getWeakCount() const;
3、三个重要的变量
weakref_impl中有三个重要的变量:
std::atomic<int32_t> mStrong;
std::atomic<int32_t> mWeak;
std::atomic<int32_t> mFlags;
mStrong为强指针计数、mWeak为弱指针计数、mFlags为控制释放内存的标志。
mFlags的取值有:
enum {
OBJECT_LIFETIME_STRONG = 0x0000,
OBJECT_LIFETIME_WEAK = 0x0001,
OBJECT_LIFETIME_MASK = 0x0001
};
OBJECT_LIFETIME_STRONG :默认值,有申请强指针时,最后一个强指针删除时,对象被清0,没有申请强指针时,最后一个弱指针被删除时清0
OBJECT_LIFETIME_WEAK:最后一个指针被删除时清0
通过extendObjectLifetime 可以修改mFlags,从而修改对象的生命周期。
4、RefBase的使用
(1)先强化再弱化
class A : public RefBase
{
}
int main()
{
A* PA = new A;
{
sp<A> spA(pA);
wp<A> wpA(spA);
//大括号结束,先析构wp,再析构sp
}
}
sp<A>强指针作用:A继承RefBase,所以有一个weakref_impl对象,sp<A>使A中weakref_impl对象的mStrong和mWeak各加1.
sp<T>
==> m_ptr -> incStrong ()
==> refs->incWeak()
==> refs->mStrong.fetch_add(1, std::memory_order_relaxed);
template<typename T>
sp<T>::sp(const sp<T>& other)
: m_ptr(other.m_ptr) {
if (m_ptr)
m_ptr->incStrong(this);
}
void RefBase::incStrong(const void* id) const
{
weakref_impl* const refs = mRefs;
refs->incWeak(id);
refs->addStrongRef(id);
const int32_t c = refs->mStrong.fetch_add(1, std::memory_order_relaxed);
ALOG_ASSERT(c > 0, "incStrong() called on %p after last strong ref", refs);
#if PRINT_REFS
ALOGD("incStrong of %p from %p: cnt=%d\n", this, id, c);
#endif
if (c != INITIAL_STRONG_VALUE) {
return;
}
int32_t old __unused = refs->mStrong.fetch_sub(INITIAL_STRONG_VALUE, std::memory_order_relaxed);
// A decStrong() must still happen after us.
ALOG_ASSERT(old > INITIAL_STRONG_VALUE, "0x%x too small", old);
refs->mBase->onFirstRef();
}
wp<A>弱指针作用:wp<A>使A中weakref_impl对象的mWeak加1.
并且通过m_refs保存影子对象和m_ptr保存实际对象
template<typename T>
wp<T>::wp(T* other)
: m_ptr(other)
{
if (other) m_refs = other->createWeak(this);
}
RefBase::weakref_type* RefBase::createWeak(const void* id) const
{
mRefs->incWeak(id);
return mRefs;
}
(2)如何自动清除对象
{
sp<A> spA(pA);
wp<A> wpA(spA);
//大括号结束,先析构wp,再析构sp
}
上面代码段运行完后,会调用wpA的析构函数,再调spA的析构函数。
函数调用:
//先析构wp,把mWeak减1
~wp()
==>m_refs->decWeak(this)
==> impl->mWeak.fetch_sub(1, std::memory_order_release);
//再析构sp
~sp()
==>m_ptr->decStrong(this)
==>refs->mStrong.fetch_sub(1, std::memory_order_release);
==>delete this;//mFlags为STRONG,删除实际对象
==>refs->decWeak(id);
==>delete impl;//删除影子对象
小结:
- 先sp再wp,sp时,强弱计数各加1,wp时,弱计数加1
- mFlags为OBJECT_LIFETIME_STRONG 时:
- 强引用为0将导致实际对象被delete
- 弱引用为0将导致影子对象被delete
(3)也可以先wp再sp
int main()
{
A* PA = new A;
wp<A> wpA(PA);
sp<A> spA = wpA.promote();
}
wp使才对象A中和weakref_impl中的弱引用mWeak加1
wpA.promote()调用流程:
wpA.promote()
==> sp<T>(m_ptr,m_refs) ;
==>refs->attemptIncStrong(this);
==>incWeak(id)
==>impl->mStrong.compare_exchange_weak(curCount, curCount+1,
std::memory_order_relaxed)
wpA.promote()使强弱引用值都加1.