从零开始写android 的智能指针

Android中定义了两种智能指针类型,一种是强指针sp(strong pointer),源码中的位置在system/core/include/utils/StrongPointer.h。另外一种是弱指针(weak pointer)。其实称之为强引用和弱引用更合适一些。强指针与一般意义的智能指针概念相同,通过引用计数来记录有多少使用者在使用一个对象,如果所有使用者都放弃了对该对象的引用,则该对象将被自动销毁。
弱指针也指向一个对象,但是弱指针仅仅记录该对象的地址,不能通过弱指针来访问该对象,也就是说不能通过弱指针来调用对象的成员函数或访问对象的成员变量。要想访问弱指针所指向的对象,需首先通过wp类所提供的promote()方法将弱指针升级为强指针。弱指针所指向的对象是有可能在其它地方被销毁的,如果对象已经被销毁,wp的promote()方法将返回空指针,这样就能避免出现地址访问错的情况。

强弱智能是用来解决什么问题的呢?

1.问题是如何产生的,当我们用new 的时候,如果忘了delet。

#include <iostream>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>using namespace std;class Person{
public:string  name;Person(string n){name =n;cout<<"build person:"<<name<<endl;}void printInfo(){cout<<"i am "<<name<<endl;}~Person(){cout<<"release person:"<<name<<endl;}
};
void test_func(void)
{Person *p = new Person("zhangsan");p->printInfo();
//    Person p = Person("zhangsan");
//    p.printInfo();
}int main(int argc, char **argv)
{int i;for (i = 0; i < 2; i++)test_func();return 0;
}

那么问题产生了。

有内存泄露。

2.开始改进,使用局部变量

 Person *p = new Person("zhangsan");
    p->printInfo();
//    Person p = Person("zhangsan");
//    p.printInfo();

   析构函数执行,内存泄露没有了。

结合以上两点,继续改进。

3.  在一个类中包含另一个类的指针,在执行这个类的析构函数时, 删除另一个类的指针。

#include <iostream>
#include <string.h>using namespace std;class Person{
public:Person(){cout<<"build person"<<endl;}~Person(){cout<<"release person"<<endl;}void printInfo(){cout<<"print person"<<endl;}
};class sp {
private:Person *p;public:sp() : p(0) {}sp(Person *other){cout<<"sp( Person *other)"<<endl;p = other;}sp(const sp &other){cout<<"sp(const Person *other)"<<endl;p = other.p;}~sp(){cout<<"~sp()"<<endl;if (p)delete p;}Person *operator->(){return p;}
};void test_func(sp &other)
{sp s = other;s->printInfo();
}int main(int argc, char **argv)
{sp other = new Person();test_func(other);cout<<"main() end"<<endl;return 0;
}

 sp出现了。但是还有问题, 在上面的程序中 person被创建了一次,但是被release了两次。会产生错误。

4. 解决思路:引入计数,当是最后一个使用者,销毁p。

#include <iostream>
#include <string.h>using namespace std;class Person{private:int count=0;
public:Person(){cout<<"build person"<<endl;}~Person(){cout<<"release person"<<endl;}void printInfo(){cout<<"print person"<<endl;}void incStrong(){count +=1;}void decStrong(){count -=1;}int getStrongCount(){return  count;}};class sp {
private:Person *p;public:sp() : p(0) {cout<<"init sp"<<endl;}sp(Person *other){cout<<"sp( Person *other)"<<endl;p = other;p->incStrong();}sp(const sp &other){cout<<"sp(const Person *other)"<<endl;p = other.p;p->incStrong();}~sp(){cout<<"~sp()"<<endl;if (p){p->decStrong();cout<<" ~"<<p->getStrongCount()<<endl;if( p->getStrongCount() ==0){delete p;p=NULL;cout<<"delete p"<<endl;}}}Person *operator->(){cout<<"->"<<endl;return p;}
};void test_func(sp &other)
{sp s = other;s->printInfo();
}int main(int argc, char **argv)
{sp other = new Person();test_func(other);cout<<"main() end"<<endl;return 0;
}

5. 将计数count 封装成一个基类。

6.在sp类中,引入模板。

using namespace std;class RefBase{
private:int count;
public:RefBase():count(0){}void incStrong(){count++;}void decStrong(){count--;}int getStrongCount(){return count;}
};class Person:public RefBase{public:Person(){cout<<"build person"<<endl;}~Person(){cout<<"release person"<<endl;}void printInfo(){cout<<"print person"<<endl;}};
template <typename T>
class sp {
private:T *p;public:sp() : p(0) {cout<<"init sp"<<endl;}sp(T *other){cout<<"sp( Person *other)"<<endl;p = other;p->incStrong();}sp(const sp &other){cout<<"sp(const Person *other)"<<endl;p = other.p;p->incStrong();}~sp(){cout<<"~sp()"<<endl;if (p){p->decStrong();cout<<" ~"<<p->getStrongCount()<<endl;if( p->getStrongCount() ==0){delete p;p=NULL;cout<<"delete p"<<endl;}}}T *operator->(){cout<<"->"<<endl;return p;}
};void test_func(sp<Person> &other)
{sp<Person> s = other;s->printInfo();
}int main(int argc, char **argv)
{sp<Person> other = new Person();test_func(other);cout<<"main() end"<<endl;return 0;
}

   一个智能指针初见雏形了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/76509.shtml

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

相关文章

【leetcode hot 100 152】乘积最大子数组

错误解法&#xff1a;db[i]表示以i结尾的最大的非空连续&#xff0c;动态规划&#xff1a;dp[i] Math.max(nums[i], nums[i] * dp[i - 1]); class Solution {public int maxProduct(int[] nums) {int n nums.length;int[] dp new int[n]; // db[i]表示以i结尾的最大的非空连…

图论整理复习

回溯&#xff1a; 模板&#xff1a; void backtracking(参数) {if (终止条件) {存放结果;return;}for (选择&#xff1a;本层集合中元素&#xff08;树中节点孩子的数量就是集合的大小&#xff09;) {处理节点;backtracking(路径&#xff0c;选择列表); // 递归回溯&#xff…

uniapp离线打包提示未添加videoplayer模块

uniapp中使用到video标签&#xff0c;但是离线打包放到安卓工程中&#xff0c;运行到真机中时提示如下&#xff1a; 解决方案&#xff1a; 1、把media-release.aar、weex_videoplayer-release.aar放到工程的libs目录下; 文档&#xff1a;https://nativesupport.dcloud.net.cn/…

打包构建替换App名称

方案适用背景 一套代码出多个安装包&#xff0c;且安装包的应用名称、图标都不一样考虑三语名称问题 通过 Gradle 脚本实现 gradle.properties 里面定义标识来区分应用&#xff0c;如下文里的 APP_TYPEAAA 、APP_TYPEBBB// 定义 groovy 替换方法 def replaceAppName(String …

DrissionPage移动端自动化:从H5到原生App的跨界测试

一、移动端自动化测试的挑战与机遇 移动端测试面临多维度挑战&#xff1a; 设备碎片化&#xff1a;Android/iOS版本、屏幕分辨率差异 混合应用架构&#xff1a;H5页面与原生组件的深度耦合 交互复杂性&#xff1a;多点触控、手势操作、传感器模拟 性能监控&#xff1a;内存…

达梦数据库用函数实现身份证合法校验

达梦数据库用函数实现身份证合法校验 拿走不谢~ CREATE OR REPLACE FUNCTION CHECK_IDCARD(A_SFZ IN VARCHAR2) RETURN VARCHAR2 IS TYPE WEIGHT_TAB IS VARRAY(17) OF NUMBER; TYPE CHECK_TAB IS VARRAY(11) OF CHAR; WEIGHT_FACTOR WEIGHT_TAB : WEIGHT_TAB(7,9,10,5,8,4,…

3dmax的python通过普通的摄像头动捕表情

1、安装python 进入cdm&#xff0c;打python要能显示版本号 >>>&#xff08;进入python提示符模式&#xff09; import sys sys.path显示python的安装路径&#xff0c; 进入到python.exe的路径 在python目录中安装(ctrlz退出python交互模式) 2、pip install mediapipe…

国产Linux统信安装mysql8教程步骤

系统环境 uname -a Linux FlencherHU-PC 6.12.9-amd64-desktop-rolling #23.01.01.18 SMP PREEMPT_DYNAMIC Fri Jan 10 18:29:31 CST 2025 x86_64 GNU/Linux下载离线安装包 浏览器下载https://downloads.mysql.com/archives/get/p/23/file/mysql-test-8.0.33-linux-glibc2.28…

Vite 权限绕过导致任意文件读取(CVE-2025-32395)(附脚本)

免责申明: 本文所描述的漏洞及其复现步骤仅供网络安全研究与教育目的使用。任何人不得将本文提供的信息用于非法目的或未经授权的系统测试。作者不对任何由于使用本文信息而导致的直接或间接损害承担责任。如涉及侵权,请及时与我们联系,我们将尽快处理并删除相关内容。 前言…

poi-tl

官网地址 Poi-tl Documentationword模板引擎https://deepoove.com/poi-tl github 地址 https://github.com/Sayi/poi-tl/tree/master gitcode 加速地址 GitCode - 全球开发者的开源社区,开源代码托管平台GitCode是面向全球开发者的开源社区,包括原创博客,开源代码托管,代码…

操作系统 4.1-I/O与显示器

外设工作起来 操作系统让外设工作的基本原理和过程&#xff0c;具体来说&#xff0c;它概括了以下几个关键步骤&#xff1a; 发出指令&#xff1a;操作系统通过向控制器中的寄存器发送指令来启动外设的工作。这些指令通常是通过I/O指令&#xff08;如out指令&#xff09;来实现…

琥珀扫描 2.0.5.0 | 文档处理全能助手,支持扫描、文字提取及表格识别

琥珀扫描是一款功能强大的文档处理应用程序。它不仅仅支持基本的文档扫描功能&#xff0c;还涵盖了文字提取、证件扫描、表格识别等多种实用功能。无论是学生、职员还是教师&#xff0c;都能从中找到适合自己的功能。该应用支持拍照生成电子件&#xff0c;并能自动矫正文档边缘…

jQuery UI 小部件方法调用详解

jQuery UI 小部件方法调用详解 引言 jQuery UI 是一个基于 jQuery 的用户界面和交互库,它提供了一系列小部件,如按钮、对话框、进度条等,这些小部件极大地丰富了网页的交互性和用户体验。本文将详细介绍 jQuery UI 中小部件的方法调用,帮助开发者更好地理解和应用这些小部…

浮点数比较在Eigen数学库中的处理方法

浮点数比较在Eigen数学库中的处理方法 在Eigen数学库中进行浮点数比较时&#xff0c;由于浮点数的精度问题&#xff0c;直接使用运算符通常不是推荐的做法。Eigen提供了几种更安全的方法来进行浮点数比较&#xff1a; 1. 近似相等比较 使用isApprox()函数进行近似比较&#…

Linux-----驱动

一、内核驱动与启动流程 1. Linux内核驱动 Nor Flash: 可线性访问&#xff0c;有专门的数据及地址总线&#xff08;与内存访问方式相同&#xff09;。 Nand Flash: 不可线性访问&#xff0c;访问需要控制逻辑&#xff08;软件&#xff09;。 2. Linux启动流程 ARM架构: IRAM…

Wincc脚本全部不运行

Wincc脚本全部不运行 前言解决办法操作步骤 前言 这里主要是指旧项目移植到Wincc的高版本&#xff0c;移植后界面的一些功能均会失效。&#xff08;例如脚本不执行&#xff0c;项目编辑器不可用等情况&#xff09; 解决办法 Wincc的项目文件中有Dcf文件&#xff0c;Dcf文件包…

使用numpy构建逻辑回归模型及训练流程

逻辑回归模型构建及训练流程 关于逻辑回归的数据&#xff0c;有很多学习⽤的⽰例样本。这⾥我们使⽤scikit learn提供的数据集⽣成函数来创建 具体参数可参照官网 Scikit-learn 是⽤ Python 开发的开源机器学习库&#xff0c;⼴泛⽤于数据挖掘和数据分析。 特点&#xff1a;易…

python的多线程和多进程程序编程

CPU密集型使用多进程&#xff0c;IO密集型使用多线程 查看进程ID和线程ID的命令分别是os.getpid()和threading.current_thread() 多进程使用multiprocessing就可以了&#xff0c;通常使用进程池来完成操作&#xff0c;阻塞主进程使用join方法 多线程使用threading模块&#…

代码随想录算法训练营第十五天

LeetCode题目: 654. 最大二叉树617. 合并二叉树700. 二叉搜索树中的搜索98. 验证二叉搜索树2843. 统计对称整数的数目 其他: 今日总结 往期打卡 654. 最大二叉树 跳转: 654. 最大二叉树 学习: 代码随想录公开讲解 问题: 给定一个不重复的整数数组 nums 。 最大二叉树 可以用…

[GN] Uart协议解码器源码各个方法

系列文章目录 sigrokdecode 模块学习指南 — 准备阶段 通讯协议 - Uart sigrokdecode 模块 UART协议解码器源码解析 Uart协议解码器源码各个方法 文章目录 系列文章目录引入库parity_ok注解类型枚举options参数annotations 注解annotation_rows 注解分组接收&#xff08;RX&a…