Android智能指针的理解:强指针sp和弱指针wp

691 阅读3分钟

Java中不需要程序员自己管理对象内存的分配和回收,而C/C++则需要。为了减少人为引入错误,例如指针没有初始化;new了对象没有及时delete以及野指针问题(没有置null)。Android引入智能指针概念:强指针sp和弱指针wp概念。同时通过引用计数来统计对象引用的情况,当被引用时,计数+1,取消引用时,计数-1,当计数为0的时候,自动释放内存,即调用delete。

这意味着需要进行内存管理的对象,需要继承基类,实现了上面引用计数的功能。

源码目录:

system/core/libutils/include/utils/RefBase.h

system/core/libutils/LightRefBase.h

system/core/libutils/include/utils/StrongPointer.h

强指针sp声明了一个私有指针m_ptr,用于指向我们要管理的内存对象。通过构造函数初始化列表会对m_ptr进行初始化,并调用内存对象的incStrong方法,增加引用计数。

template<typename T>
sp<T>::sp(T* other)
        : m_ptr(other) {//构造函数初始化列表
    if (other) {
        check_not_on_stack(other);
        other->incStrong(this);//增加对象的引用计数
    }
}

另一个就是"="重载,在使用“=”指向一个新对象,如果已指向旧对象,需要调用旧对象的decStrong方法,减少计数,再调用新对象的incStrong增加计数。

template<typename T> template<typename U>
sp<T>& sp<T>::operator =(const sp<U>& other) {
    T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
    T* otherPtr(other.m_ptr);
    if (otherPtr) otherPtr->incStrong(this);//新指向的对象需要增加引用计数
    if (oldPtr) oldPtr->decStrong(this);//旧对象需要减少引用计数
    if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
    m_ptr = otherPtr;//指针指向新的内存对象
    return *this;
}

StrongPointer.h文件中很多方法都是操作指针m_ptr,以及内存对象的incStrongdecStrong方法。Android提供了LightRefBaseRefBase,用于管理对象引用计数。前者较轻量级,只提供强指针引用相关能力,非线程安全;后者同时提供强指针和弱指针能力,线程安全。 RefBase提供了生命周期的回调:onFirstRefonLastStrongRefonLastWeakRef

弱指针是为了解决父对象parent指向子对象child,然后子对象又指向父对象这种循环引用的现象问题。

弱指针规定父类使用强指针指向子类,子类使用弱指针指向父类,当强指针为0时,就可以delete自己。弱指针需要升级为强指针,才能访问它所指的目标对象。

弱指针类wp提供了promote方法用于升级为强指针。如果在升级过程,返回null表示升级失败,目标对象已经被delete了。

综上所述,简单的理解:

在Android native层C++编码中,我们可以使用Android提供的智能指针,我们创建的对象需要继承自LightResBase或RefBase,然后将对象赋值给sp或者wp,把对象的内存分配和回收交给了智能指针这个机制,避免文章开头说提的,人为引入问题。