安卓智能指针sp、wp、RefBase浅析

目录

  • 前言
  • 一、RefBase
    • [1.1 引用计数机制](#1.1 引用计数机制)
    • [1.2 设计目的](#1.2 设计目的)
    • [1.3 主要方法](#1.3 主要方法)
    • [1.4 如何使用](#1.4 如何使用)
    • [1.5 小结](#1.5 小结)
  • 二、sp和wp
    • [2.1 引用计数机制](#2.1 引用计数机制)
    • [2.2 设计目的](#2.2 设计目的)
    • [2.3 主要方法](#2.3 主要方法)
      • [2.3.1 sp](#2.3.1 sp)
      • [2.3.2 wp](#2.3.2 wp)
    • [2.4 如何使用](#2.4 如何使用)
    • [2.5 小结](#2.5 小结)
  • 四、参考链接

前言

安卓底层binder中,为什么 IInterface要继承自RefBase ?常常看到的sp又是什么东西?想要搞懂安卓底层binder,又或是安卓NDK开发,你必须了解这些内容。

一、RefBase

RefBase 是 Android 系统中用于实现引用计数的基类,主要用于管理对象的生存周期。其设计是为了确保在多线程和多组件的环境中正确处理对象的引用计数,从而提高内存管理的安全性和效率。

1.1 引用计数机制

当一个对象被创建时,它的引用计数初始为 1。每当一个新的引用指向该对象时,引用计数加一;每当引用失效时,引用计数减一。当引用计数减到 0 时,对象的析构函数会被调用,内存将被释放。这样可以有效避免内存泄漏并确保在不需要时释放资源。

1.2 设计目的

在多线程环境中,使用引用计数可以使得对象的管理更加安全。当多个线程或组件引用同一个对象时,引用计数机制可以确保对象在引用未被完全释放之前不被销毁,避免了潜在的使用已释放对象的危害。

1.3 主要方法

RefBase 提供了一些基础方法来支持引用计数,例如:

  • incStrong() 和 decStrong():

这两个方法分别用于增加和减少对象的强引用计数。强引用保证了对象在有强引用存在时不会被销毁。

  • incWeak() 和 decWeak():

这些方法用于弱引用计数管理。弱引用允许对象在没有强引用时被销毁,因此不会阻止对象的析构。

  • getStrongCount() 和 getWeakCount():

返回当前的强引用和弱引用计数。

1.4 如何使用

在 Android 中,通常会通过 sp< T>wp< T> 类来使用 RefBase 的引用计数功能。
sp< T> 是一个智能指针,表示强引用,持有对象的强引用;

wp< T> 表示弱引用,持有对象的弱引用。

示例代码:

c 复制代码
#include <utils/RefBase.h>

class MyObject : public RefBase {  
public:  
    MyObject() { }  
    ~MyObject() { }  

    void doSomething() {  
        // 业务逻辑  
    }  
};  
int main() {  
    sp<MyObject> obj = new MyObject(); // 引用计数为 1  
    {  
        sp<MyObject> obj2 = obj; // 引用计数增加到 2  
        obj2->doSomething(); // 可以通过 obj2 调用方法  
    } // obj2 生命周期结束,引用计数减少到 1  
    
    // 继续使用 obj,不会被提前销毁  
    obj->doSomething();  

    // 当 obj 超出作用域后,引用计数减少到 0,对象会被销毁  
    return 0;  
}

1.5 小结

RefBase 是 Android 中用于引用计数的基础类。

提供了强引用和弱引用的管理机制,确保在多线程环境中安全地管理对象的生命周期。

使用 sp 和 wp 管理对象时,可以方便地实现内存安全和避免内存泄漏的风险。


二、sp和wp

强指针sp(Strong Pointer)和弱指针wp(Weak Pointer)

2.1 引用计数机制

sp 是一个智能指针,它使用引用计数机制来管理资源。当一个 sp 指针被复制时,它会增加对象的引用计数;当 sp 指针被销毁时,它会减少引用计数。

wp同理,只不过是区分为强引用计数和弱引用计数。

当引用计数变为零时(即没有任何 sp 指针指向该对象),对象会自动被销毁,释放所占的内存。

2.2 设计目的

  • 内存管理:通过引用计数机制,sp 和 wp 旨在简化对象的内存管理,避免内存泄露和不必要的内存占用。
  • 防止循环引用:使用 sp 和 wp,可以避免由于相互引用导致的循环引用,从而使对象无法释放。

2.3 主要方法

2.3.1 sp

  • 提供多种形式的构造方式
  • 定义多种形式的赋值运算操作
  • 重载操作运算符*,可以获取实际对象
  • 重载操作运算符->,可以获取指向实际对象的指针
  • 可通过get函数,获取实际对象的指针
  • force_set函数可以指定sp引用的实际对象,该函数设计有点缺点,若sp当前已经引用其他的对象,则可能造成其他对象无法释放。

2.3.2 wp

  • 提供多种形式的构造方式
  • 定义多种形式的赋值运算操作
  • 可通过unsafe_get函数,获取实际对象的指针,但是可能获取到的是空的或是野指针
  • 可以通过promote函数将弱引用变为强引用,这个是一个比较重要的函数。

2.4 如何使用

一个简单的小demo

c 复制代码
#include <utils/RefBase.h>  
#include <iostream>  

class MyClass : public android::RefBase {  
public:  
    MyClass(int value) : mValue(value) {  
        std::cout << "MyClass created with value: " << mValue << std::endl;  
    }  
    
    ~MyClass() {  
        std::cout << "MyClass destroyed with value: " << mValue << std::endl;  
    }  

    void displayValue() {  
        std::cout << "Value: " << mValue << std::endl;  
    }  

private:  
    int mValue;  
};  

void demonstrateSpAndWp() {  
    // 创建一个 sp 指向 MyClass 的实例  
    android::sp<MyClass> strongPtr = new MyClass(42);  
    strongPtr->displayValue(); // 使用 sp 指针调用方法  

    // 创建一个 wp 指向 sp 指针的对象  
    android::wp<MyClass> weakPtr = strongPtr;  

    // 尝试通过 wp 转换为 sp  
    if (android::sp<MyClass> tempPtr = weakPtr.promote()) {  
        tempPtr->displayValue(); // 使用转换后的 sp 指针调用方法  
    } else {  
        std::cout << "The object is already destroyed!" << std::endl;  
    }  

    // 删除 strongPtr,强引用计数减一  
    strongPtr = nullptr; // 这会导致 MyClass 对象被销毁  
    std::cout << "strongPtr set to nullptr." << std::endl;  

    // 再次检查 wp 指针  
    if (android::sp<MyClass> tempPtr = weakPtr.promote()) {  
        tempPtr->displayValue(); // 尝试访问已经被销毁的对象  
    } else {  
        std::cout << "The object is already destroyed!" << std::endl;  
    }  
}  

int main() {  
    demonstrateSpAndWp();  
    return 0;  
}

创建一个 sp 指针 strongPtr,指向 MyClass 的实例。调用对象的方法来展示功能。

创建一个 wp 指针 weakPtr,指向 strongPtr。此时对象的引用计数依然有效。

使用 promote() 方法将 wp 转换为一个 sp 指针,以检查对象是否仍然有效并使用它。

将 strongPtr 置为空以释放对象,这将导致 MyClass 的析构函数被调用。

再次检查 weakPtr 指向的对象,证明对象已经被销毁,此时 promote() 将返回空指针,输出相关信息。

2.5 小结

  • sp 和 wp 是 Android 提供的智能指针类,使用引用计数机制来实现内存管理。
  • sp 主要用于对对象的强引用,自动管理对象的生命周期;
  • wp 用于对对象的弱引用,允许检测被引用对象的有效性,同时不会影响其生命周期。
  • 正确使用 sp 和 wp 可以有效地减少内存泄漏、提高内存管理的安全性,并防止循环引用问题。

四、参考链接

说了半天,为什么要用引用计数功能?sp、wp、RefBase的源码深度解析?

请看链接文章内容

Android智能指针RefBase、sp、wp解析

相关推荐
东风吹柳16 分钟前
观察者模式(sigslot in C++)
c++·观察者模式·信号槽·sigslot
A懿轩A24 分钟前
C/C++ 数据结构与算法【栈和队列】 栈+队列详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·栈和队列
居居飒34 分钟前
Android学习(四)-Kotlin编程语言-for循环
android·学习·kotlin
大胆飞猪2 小时前
C++9--前置++和后置++重载,const,日期类的实现(对前几篇知识点的应用)
c++
1 9 J2 小时前
数据结构 C/C++(实验五:图)
c语言·数据结构·c++·学习·算法
夕泠爱吃糖2 小时前
C++中如何实现序列化和反序列化?
服务器·数据库·c++
长潇若雪2 小时前
《类和对象:基础原理全解析(上篇)》
开发语言·c++·经验分享·类和对象
Henry_He3 小时前
桌面列表小部件不能点击的问题分析
android
工程师老罗4 小时前
Android笔试面试题AI答之Android基础(1)
android
染指11104 小时前
50.第二阶段x86游戏实战2-lua获取本地寻路,跨地图寻路和获取当前地图id
c++·windows·lua·游戏安全·反游戏外挂·游戏逆向·luastudio