Android 系统C++智能指针----总结

本文介绍了Android系统中C++智能指针的概念和作用,详细解析了智能指针的强指针和弱指针的实现原理,包括RefBase基类、引用计数管理和升级为强引用的过程。通过理解智能指针,有助于Android开发者更好地管理和防止内存泄漏。
摘要由CSDN通过智能技术生成

一、前言

想要成为一名优秀的Android开发者, 我们避免不了要深入Android系统进行学习。只有搞明白了Android系统的运行机制、原理,我们才能更加得心应手的开发出性能优越的Android应用。

当然,在进行深入学习之前我们也需要具有一定的基础(例如:C++),想要深入学习Android系统的朋友们还是有必要先去学习C++的。因为在Android底层很多的核心功能都是使用C++开发出来的。

二、什么是智能指针?

使用过C++的朋友肯定都知道C++的指针,使用起来非常方便,功能强大。但是也有不足之处,就是我们必须自己去管理指针的释放,否则就会造成内存泄漏甚至程序崩溃。

那么Android在使用C++的时候, 提供了一个很方便的工具,就是智能指针。目的是帮助我们来进行对象的释放工作。其使用的基本原理就是引用计数法。
我们可以对智能指针做一些总结:

  • 一种能够自动维护对象引用计数的技术
  • 智能指针一是个对象,而不是一个指针
  • 智能指针分为强指针、弱指针
  • Android定义了一个公共基类,所有想要使用智能指针的类都要继承它

三、智能指针的公共基类

Android OS 8.0.0_r4
/system/core/include/utils/RefBase.h

class RefBase
{
public:
            void            incStrong(const void* id) const; // 增加强引用
            void            decStrong(const void* id) const; // 减少强引用
			
			// ... 

			// 内部类表示弱引用类型
		    class weakref_type
		    {
		    public:
		        RefBase*            refBase() const;
		        void                incWeak(const void* id); // 增加弱引用
		        void                decWeak(const void* id); // 减少弱引用
		        bool                attemptIncStrong(const void* id); // 尝试获取强引用对象,在弱引用升级强引用时会调用
		    };

            weakref_type*   createWeak(const void* id) const;  // 创建弱引用
            weakref_type*   getWeakRefs() const;
			typedef RefBase basetype;

protected使用:
                            RefBase();
   virtual                 ~RefBase();//  虚析构函数,子类也要使用虚析构函数,当基类指针指向派生对象时, 如果不是虚析构函数,delete不会调用派生对象的析构函数,就有可能造成泄露
    
    //标记生命周期的模式
    enum {
        OBJECT_LIFETIME_STRONG  = 0x0000, // 生命周期只跟强引用有关, 当强引用为0时释放对象
        OBJECT_LIFETIME_WEAK    = 0x0001, // 生命周期只跟弱引用有关, 当弱引用为0时释放对象
        OBJECT_LIFETIME_MASK    = 0x0001
    };
    
    void            extendObjectLifetime(int32_t mode); // 设置生命周期类型
            
    //! Flags for onIncStrongAttempted()
    enum {
        FIRST_INC_STRONG = 0x0001
    };
    
   // 生命周期变化时的回调,后面分析中会提到具体的回调时机
    virtual void            onFirstRef();
    virtual void            onLastStrongRef(const void* id);
    virtual bool            onIncStrongAttempted(uint32_t flags, const void* id);
    virtual void            onLastWeakRef(const void* id);

private:
    friend class weakref_type;				 // 声明友源类
    class weakref_impl;						 // 声明类 weakref_impl
               RefBase(const RefBase& o); 	 // 构造方法
    RefBase&   operator=(const RefBase& o);  // 重载运算符: =

private:
        weakref_impl* const mRefs; // 持有一个类weakref_impl的对象,用来管理强/弱引用计数
};

我们上面说到, 智能指针使用的是引用计数法。那么在上面好像并没有看到用来计数的变量。
其实RefBase使用的是weakref_impl来维护强引用计数和弱引用计数的。我们下面看一下weakref_impl的代码。

/system/core/libutils/RefBase.cpp

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;  // 生命周期类型标记

#if !DEBUG_REFS

    explicit weakref_impl(RefBase* base)
        : mStrong(INITIAL_STRONG_VALUE) // 强引用计数初始化的值, 不是0
        , mWeak(0)
        , mBase(base)
        , mFlags(0)
    {
    }

	// 非调试模式下都是空实现
    void addStrongRef(const void* /*id*/) { }
    void removeStrongRef(const void* /*id*/) { }
    void renameStrongRefId(const void* /*old_id*/, const void* /*new_id*/) { }
    void addWeakRef(const void* /*id*/) { }
    void removeWeakRef(const void* /*id*/) { }
    void renameWeakRefId(const void* /*old_id*/, const void* /*new_id*/) { }
    void printRefs() const { }
    void trackMe(bool, bool) { }

#else
...调试模式
#endif
};

上面一共看到了三个类,RefBase、weakref_type、weakref_impl。
每一个RefBase对象都包含了一个weakref_impl对象,而weakref_impl继承了weakref_type。

当我们自己的类想要使用智能指针的时候, 只需要继承RefBase就可以了。这样我们的类就拥有了weakref_impl类型的成员变量, 用来维护当前对象的引用计数。当我们把对象赋值给强指针(sp<>)或者弱指针(wp<>)的时候, 就可以不用去管理强弱指针的释放工作了, 不用的时候只需要给强弱指针赋值为NULL就可以了。

四、智能指针的强指针实现类

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


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值