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

news/2024/11/8 16:46:29 标签: android, binder, c++

目录

  • 前言
  • 一、RefBase
    • 1.1 引用计数机制
    • 1.2 设计目的
    • 1.3 主要方法
    • 1.4 如何使用
    • 1.5 小结
  • 二、sp和wp
    • 2.1 引用计数机制
    • 2.2 设计目的
    • 2.3 主要方法
      • 2.3.1 sp
      • 2.3.2 wp
    • 2.4 如何使用
    • 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> 表示弱引用,持有对象的弱引用。

示例代码:

#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

#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解析


http://www.niftyadmin.cn/n/5744168.html

相关文章

Threejs随机生成建筑

生成建筑&#xff0c;重点在于&#xff0c;什么&#xff1f; 答案当然是数量&#xff0c;生成的建筑过多&#xff0c;那么一定会卡顿模糊&#xff0c;所以。生成建筑的难点而是在于对性能的优化。优化的解决方案就是&#xff1a;BufferGeometryUtils BufferGeometryUtils的用…

ubuntu22.04 docker-compose安装postgresql数据库

在 Ubuntu 22.04 上使用 Docker Compose 来安装和运行 PostgreSQL 数据库的过程如下&#xff1a; 1. 创建 Docker Compose 文件 在项目文件夹中创建一个 docker-compose.yml 文件&#xff0c;以配置 PostgreSQL 数据库的服务。 mkdir postgres_docker cd postgres_docker to…

基于MATLAB的实现垃圾分类Matlab源码

⼀、垃圾分类 如何通过垃圾分类管理&#xff0c;最⼤限度地实现垃圾资源利⽤&#xff0c;减少垃圾处置量&#xff0c;改善⽣存环境质量&#xff0c;是当前世界各国共同关注的迫切问题之⼀。根据国家制定的统⼀标准&#xff0c;现在⽣活垃圾被⼴泛分为四类&#xff0c;分别是可…

.Net IOC理解及代码实现

IOC理解 IoC(Inversion of Control)&#xff1a;即控制反转&#xff0c;这是一种设计思想&#xff0c;指将对象的控制权交给IOC容器&#xff0c;由容器来实现对象的创建、管理&#xff0c;程序员只需要从容器获取想要的对象就可以了。DI(Dependency Injection)&#xff0c;即依…

【学习笔记】SAP ABAP——OPEN SQL(一)【INTO语句】

【INTO语句】 结构体插入(插入一条语句时) SELECT...INTO [CORRESPONDING FIELDS OF] <wa> FROM <db> WHERE <condition>.内表插入(插入多条语句时) SELECT...INTO|APPENDING [CORRESPONDING FIELDS OF] TABLE <itab>FROM <db> WHERE <con…

计算机网络——HTTP篇

基础篇 IOS七层网络模型 TCP/IP四层模型&#xff1f; 应⽤层&#xff1a;位于传输层之上&#xff0c;主要提供两个终端设备上的应⽤程序之间的通信&#xff0c;它定义了信息交换的格式&#xff0c;消息会交给下⼀层传输层来传输。 传输层的主要任务就是负责向两台设备进程之间…

OpenSSL 生成根证书、中间证书和网站证书

OpenSSL 生成根证书、中间证书和网站证书 一、生成根证书&#xff08;ChinaRootCA&#xff09;二、生成中间 CA&#xff08;GuangDongCA&#xff09;三、生成网站证书&#xff08;gdzwfw&#xff09; 一、生成根证书&#xff08;ChinaRootCA&#xff09; 创建私钥&#xff1a; …

43.第二阶段x86游戏实战2-提取游戏里面的lua

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 本人写的内容纯属胡编乱造&#xff0c;全都是合成造假&#xff0c;仅仅只是为了娱乐&#xff0c;请不要…