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

目录

  • 前言
  • 一、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.rhkb.cn/news/466685.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

k8s 上如何跑 Dolphins 模型

接着上一篇的介绍&#xff0c;这一篇就来跑跑 Dolphins 模型&#xff0c;本篇会记录&#xff0c;跑模型常见的阬点。 1 在 k8s 上创建 pod 将外部数据挂载在 pod 里&#xff0c;并申请 gpu 资源。同时修改代码里对应的引入数据的路径 # dolphins.yaml apiVersion: v1 kind: …

CentOS 7 更换软件仓库

CentOS 7 于2024年6月30日停止维护&#xff0c;官方仓库已经没有软件了&#xff0c;想要继续使用 &#xff0c;需要更换软件仓库&#xff0c;这里更换到阿里云的软件仓库 https://developer.aliyun.com/mirror/ 查看目前可用的软件数量 yum repolist 更换软件仓库&#xff1a…

初学者指南:用例图——开启您的软件工程之旅

目录 背景&#xff1a; 基本组成&#xff1a; 关联&#xff08;Assciation&#xff09;&#xff1a; 包含&#xff08;Include&#xff09;&#xff1a; 扩展&#xff08;Extend&#xff09;&#xff1a; 泛化&#xff08;Inheritance&#xff09;&#xff1a; 完整银行…

单位正交矢量的参数化,用于特征矢量对厄尔米特矩阵对角化使用

​ 首先α β 在0-pi/2内&#xff0c;这样就可以取值0-1&#xff0c;满足了单位化的要求 每个向量的模由α和β定义&#xff0c;αβ定义模的时候只限制在0–pi/2&#xff0c;由画图可知不可正交 为了验证矩阵 U 3 \boldsymbol{U}_3 U3​ 的第一列和第二列是否正交&#xff…

Spring Security 框架篇-深入了解 Spring Security 的授权核心功能(RBAC 权限模型、自定义异常处理器、校验权限方法)

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 权限系统 1.1 引入 1.2 RBAC 权限模型 1.3 数据库设计 2.0 Spring Security 核心功能-授权 2.1 思路分析 2.2 编写 SQL 语句 2.3 将用户权限进行封装 2.4 获取用户…

使用 API 和离线库查询 IP 地址方法详解

目录 一、IP 地址查询能获取哪些信息1.地理位置信息2.网络信息3.网络类型 二、IP 地址查询方法&#xff0c;附代码1.在线查询 IP 地址方法2.使用 API 进行 IP 地址查询3.使用离线库进行 IP 地址查询 互联网监管部门要求公开 IP 归属地&#xff0c;引起了很大热度&#xff0c;但…

微服务day02

教学文档&#xff1a; 黑马教学文档 Docker Docker的安装 镜像和容器 命令解读 常见命令 案例 查看DockerHub&#xff0c;拉取Nginx镜像&#xff0c;创建并运行容器 搜索Nginx镜像&#xff1a;在 www.hub.docker.com 网站进行查询 拉取镜像&#xff1a; docker pull ngin…

一个小程序如何对接多个收款账户?

背景 我又来了&#xff0c;之前对接过网约巴士系统 网约巴士旅游专线平台搭建历程&#xff0c;运营了两年多了。在运营中完善、在完善中学习&#xff0c;一直是不变的真理。有一句话说得好&#xff1a;先做一个垃圾、用起来再说。 今天又需要升级了&#xff0c;需求是&#…

基于航片的玉米异常情况识别赛题正在报名中 | CCF BDCI进行时

一年一度的行业盛事2024 CCF大数据与计算智能大赛&#xff08;简称2024 CCF BDCI&#xff09;又在激烈进行中啦 多个赛题等你挑战&#xff0c;还没有报名的伙伴们抓紧时间咯&#xff0c;叫上你伙伴练起来吧&#xff01; 2024 CCF大数据与计算智能大赛 CCF大数据与计算智能大…

面试题:Spring(一)

1. Spring框架中bean是单例么&#xff1f; Service Scope("singleton") public class UserServiceImpl implements UserService { }singleton : bean在每个Spring IOC容器中只有一个实例。prototype&#xff1a;一个bean的定义可以有多个实例。 2. Spring框架中的…

Android View事件分发

目录 1.什么是View事件分发&#xff1f; 2.事件的类型 3.事件的发生 4.事件分发的方法 4.1 dispatchTouchEvent() 4.2 onTouchEvent() 4.3 onInterceptTouchEvent() 5.滑动冲突 5.1 外部拦截法 5.2内部拦截法 6.onTouch的执行高于onClick 7. onTouch()和onTouchEve…

uniapp 实现瀑布流

效果演示 组件下载 瀑布流布局-waterfall - DCloud 插件市场

6.qsqlquerymodel源码分析

目录 继承关系入口浅析qsqlquery刷新数据 扩展列或者移除列以及取别名读取数据与增减行读取数据 下一章节&#xff1a;如何使用qsqlquerymodel 与 qtableview实现自定义表格 继承关系 qsqlquerymodel 继承与qabstracttablemodel 入口 负责填充数据 void QSqlQueryModel::s…

Vue3中使用LogicFlow实现简单流程图

实现结果 实现功能&#xff1a; 拖拽创建节点自定义节点/边自定义快捷键人员选择弹窗右侧动态配置组件配置项获取/回显必填项验证历史记录&#xff08;撤销/恢复&#xff09; 自定义节点与拖拽创建节点 拖拽节点面板node-panel.vue <template><div class"node-…

Devops业务价值流:软件研发最佳实践

在当今快速迭代的软件开发环境中&#xff0c;DevOps业务价值流已成为推动软件研发高效与质量并重的关键实践。软件研发阶段作为产品生命周期的核心环节&#xff0c;其每一步都承载着将创意转化为现实的重要使命。在历经需求澄清的精准定位、架构设计的宏观规划以及项目初始化的…

wireshark工具使用

复制数据 1.右键展开整帧数据 2.复制“所有可见项目” mark标记数据 标记&#xff1a; 跳转&#xff1a; 保存成文件&#xff1a; 文件–>导出特定分组—>Marked packets only

管理 Elasticsearch 变得更容易了,非常容易!

作者&#xff1a;来自 Elastic Ken Exner Elasticsearch 用户&#xff0c;我们听到了你的心声。管理 Elasticsearch 有时会变得很复杂&#xff0c;面临的挑战包括性能调整、问题检测和资源优化。我们一直致力于简化你的体验。今天&#xff0c;我们宣布了自收购 Opster 以来的一…

深度洞察| 超6亿银发精准流量,40+泛银发群体参与消费三大变化

作者 | NewAgingPro团队 前言 9月24日&#xff0c;AgeClub成立银发流量及场景联盟&#xff08;简称&#xff1a;AgeMCN&#xff09;&#xff0c;助力银发经济高质量发展。 10月11日&#xff0c;AgeClub发布《2024银发流量全景洞察报告》&#xff0c;探索银发流量发展新模式…

Spring Boot——日志介绍和配置

1. 日志的介绍 在前面的学习中&#xff0c;控制台上打印出来的一大堆内容就是日志&#xff0c;可以帮助我们发现问题&#xff0c;分析问题&#xff0c;定位问题&#xff0c;除此之外&#xff0c;日志还可以进行系统的监控&#xff0c;数据采集等 2. 日志的使用 在程序中获取日…

Redis 组网方式入门

文章目录 一、组网方式1. 单实例模式描述优点缺点适用场景 2. 主从复制模式&#xff08;Master-Slave Replication&#xff09;描述优点缺点适用场景基于docker的redis主从复制1. 配置主节点2. 配置从节点3. 查看节点状态4. 验证主从数据同步5. 查看同步进度 3. 哨兵模式&#…