在C++中,我们常用指针去使用某个对象实例,但随着代码对该对象使用的增加,比如越来越多的其它的类或模块需要使用该对象,那么什么时候安全地释放该对象就是个问题。比如,某处使用完该对象后,认为不再使用,便释放了它,但另外的某些类或模块还需使用,这时,就会引起内存的非法使用问题,在Linux下是signal 11错误,也就是段错误(Segmentation Fault)。为了解决这种问题,引入了智能指针,当使用该对象时,令其引用计数加1,释放时只是减去1。当减为0时,就自动释放指针所指对象。C++中,通常使用模板实现这一机制。但是当两个智能指针相互引用对方时,即使其它地方都释放它们,它们的引用计数也会为1,最终导致内存泄漏。这就引入了弱指针的概念。 Android中的随处可见的sp<XXX>和wp<XXX>。这里的XXX是对象的类,sp和wp是模版,分别实现了强指针(Strong Pointer)和弱指针(Weak Pointer)。模板具体化后的一个实例XXX,具有指针的属性,可以简单地把它理解一个指针,只不过比普通的指针特殊一点而已。弱指针不能直接被当作指针来使用,当需要当作指针来使用时,需要使用其成员函数promote来“提升”为强指针。弱指针指向的对象可能已经被销毁,这时,若使用promote得到的指针为空指针。
引用计数功能的实现 RefBase是引用计数的基类(见文件RefBase.h),在它里面还定义了一个嵌套类weakref_type,在其实现文件RefBase.cpp里还定义了一个类weakref_impl ,它继承自嵌套类weakref_type,而RefBase中包含一个私有数据成员:指向weakref_impl 的指针。可以看出,RefBase中的数据实体就是weakref_impl,后者继承自其嵌套类weakref_type。其示意图如下:
这样,相当于将一部分成员函数(weakref_type的成员函数)和数据成员(weakref_impl的数据成员)封装起来,作为私有的一个逻辑实体,只被Refbase内部的实现使用,而RefBase的公有成员才是外界使用的API。RefBase通过指针mRefs使用内部的引用计数数据。而内部引用计数实体对象也可以通过 mBase这个成员来使用其“容器”对象RefBase. weakref_impl里面的数据成员信息如下: volatile int32_t mStrong;//强引用计数
强指针和弱指针都是模板类: template <typename T> class sp{ //……此处省略了部分代码 inline T& operator* () const { return *m_ptr; } //……此处省略了部分代码 T* m_ptr;//实际指向对象的指针 }; template <typename T> class wp{ //……此处省略了部分代码 sp<T>promote() const; //……此处省略了部分代码 T* m_ptr; }; 强指针因为重载了两个操作符*和->,因此具有形式上跟普通指针一样的用法,而弱指则没有重载这两个操作符,只能先被“提升”为强指针后,才可以当作普通指针来使用。 如果需要使用智能指针将对象保护起来,只要让其继承RefBase,并将析构函数声明为virtual的,就可以使用智能指针。
可以参考链接来获取详细介绍:
参考: Android系统的智能指针(轻量级指针、强指针和弱指针)的实现原理分析 |
|