【iOS】引用计数(一)

news2024/11/18 22:53:51

【iOS】引用计数

文章目录

  • 【iOS】引用计数
    • 前言
    • ARC与MRC
    • 什么是引用计数的机制
    • 内存管理的思考方式
      • 自己生成的对象
      • 非自己生成的对象
      • 不再需要自己持有就释放
      • 无法释放非自己持有的对象
    • autorelease
    • 小结

前言

笔者最近开始学习了一下有关于引用计数的内容,写这篇博客来简单认识一下引用计数部分的内容。

ARC与MRC

ARC就是自动引用计数,指的是OC中对于引用计数采取一个自动计数的方式。

在Objective-C中采用Automatic Reference Counting
(ARC)机制,让编译器来进行内存管理。在新一代Apple
LLVM编译器中设置ARC为有效状态,就无需再次键入retain或者release代码,这在降低程序崩溃、内存泄漏等风险的同时,很大程度上减少了开发程序的工作量。编译器完全清楚目标对象,并能立刻释放那些不再被使用的对象。如此来,应用程序将具有可预测性,且能流畅运行,速度也将大幅提升。

MRC则是由程序员手动进行内存管理,很显然ARC极大的提高了开发效率,也可以让程序更加流畅的运行。

什么是引用计数的机制

我们可以通过一个开关灯的思路去理解这部分内容,

在这里插入图片描述

正如上图所展示的,我们办公室在第一个人来的时候就要开灯,在最后一个人走后就要关灯,不能在当一个人走后就进行一个关灯操作,这样会影响其他人工作,所以只有当最后一个人离开办公室的时候再关灯就好了,这样才可以让其他人正常工作,而我们创建的对象可以理解为办公室里的照明设备,只要有一个人工作,照明设备就不可以被关闭。

OC中对应的一个状态对照明设备的操作
生成对象开灯
持有对象办公室还有人需要照明
释放对象不需要照明
废弃对象关灯

可以看到这里对象是否要被释放和我们这里办公室里面是否还有人关系非常密切,所以OC就采用了一种引用计数的方式来记录该对象是否要被释放,我们分析一下灯的开关被打开的几个过程,首先开始是没有人的状态这时候引用计数为0,后面有第一个人之后,引用计数为1,然后又来一个人引用计数为2,然后有人离去的时候引用计数减一,最后一个人离开的时候引用计数再减一,这时候我们就可以把这个灯关掉,这里我们把上述的灯改成对象,所以这里就简单介绍了我们对象的概念。

在这里插入图片描述

下面这张图就展示了我们的引用计数这个机制的几个步骤。

内存管理的思考方式

我们思考内存管理的时候,往往会过于关注计数这个问题,但是实际上计数反而不是重点,我们真正的应该思考的应该是如下四个方式来分引用计数。

  • 自己生成的对象,自己持有;
  • 非自己生成的对象,自己也能持有;
  • 不再需要自己持有的对象时释放;
  • 非自己持有的对象无法释放。

在这里插入图片描述
这个表格给出了OC中对应的操作。

自己生成的对象

id obj = [[NSObject alloc] init];id obj = [NSObject new];这两个都是自己生成对象自己持有。

我们按着驼峰命名法也可以来自己生成并且持有对象。

非自己生成的对象

我们使用出来非上述的方式也可以取得一个对象,但是因为不是通过自己生成并且持有的方式创建的,所以我们通过类似[NSMutableArray array]的方式创建的,我们还没有实现持有这个步骤,所以我们需要进行一个持有的过程.

id obj = [NSMutableArray array];
[obj retain];

这个方法的底层实现原理其实是通过一个autorealse这个方式来实现的,至于这个方法是如何实现的我们后面简单介绍一下。

id obj = [[NSObject alloc] init];
[obj autorelease];

这里就实现一个持有的操作,这里的对象并非自己创建但是仍然可以持有该对象。

不再需要自己持有就释放

简单来说就是我们不需要持有这个对象的时候,我们就需要调用release这个代码来实现一个释放的效果,比方说:

id obj = [NSMutableArray array];
[obj retain];
[obj release];

这里注意一下,如果一个对象一经释放就不可以再访问了。

无法释放非自己持有的对象

在OC中我们也无法释放非自己持有的对象,举个例子:

id obj = [[NSObject alloc] init];
    [obj release];
    [obj release];

根据前面我们说的内容,这里我们如果已经release过一次,obj所持有的对象已经被废弃了,所以我们在释放一次的话就会出现一个程序崩溃的问题。

其实我们可以总结为以下四个方面:

在这里插入图片描述

autorelease

我们上面提到了autorelease,这里我们就来简单介绍一下有关autorelease的内容。

而autorelease是一种延迟释放对象的机制。当一个对象被autorelease时,它的引用计数不会立即减少,而是在当前autorelease pool被销毁时才会减少。
这意味着,即使你不再使用一个对象,它也不会立即被释放,而是等待当前Runloop结束时才会被释放。因此,autorelease可以在需要延迟释放对象时使用,以避免频繁释放和创建对象带来的性能开销。

在这里插入图片描述

他最大好处在于可以使取得的对象存在但是自己并不持有对象。

我们可以把它理解成一个C语言中的局部变量,C语言中的局部变量是在我们的变量超出自己的作用域的时候会被自动废弃,那么这里则是一个对象如果离开了autorelease的池中他会自己调用release这个方法。下面给出如何使用autorelsease,他有一优势就是我们可以定义变量的作用域。

在这里插入图片描述

这里我们按照上图的要求编写下面这段代码:

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    id obj = [[NSObject alloc] init];
    [obj autorelease];
    [pool drain];
     NSLog(@"%lu", [obj retainCount]);//这里会报错,因为我们无法访问到这个对象

上面这段代码展示了我们如何使用autorelease这个方法,这里的[pool drain];相当于[obj release]

但是实际上我们的编译器会自己创建NSAutoreleasePool这个类的对象,就好比我们的NSMutableArray这个类

 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    id obj = [NSMutableArray array];
    [obj autorelease];
    [pool drain];

这段代码会报错,主要原因是我们在创建NSMutableArray这个类的对象的时候,编译器会自动创建一个NSAutoreleasePool然后这个池子被放进了我们之前手动创建的NSAutoreleasePool这个池子中,所以他会把池子给释放,然后就会释放我们的数组,从而导致了我们的数组引用计数已经为0,导致代码报错。

小结

这里笔者对于引用计数进行了一个简单的学习,简单了解了他的一个相关实现,后面还会继续进行补充学习。

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

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

相关文章

自动驾驶规划算法(一):A*算法原理和代码(c++与python)

1. A*算法简介 A*算法(A-star algorithm)诞生于1968年,由彼得哈特(Peter Hart)、尼尔森尼尔森(Nils Nilsson)和伯特拉波特(Bertram Raphael)三位计算机科学家提出。它的…

[机器学习]04-逻辑回归(python)-03-API与癌症分类案例讲解

逻辑回归(Logistic Regression) 的一API 介绍 关于如何配置模型中的优化器、正则化和惩罚项。 1. 逻辑回归 API 在 Scikit-learn 中,逻辑回归可以通过如下方式定义: from sklearn.linear_model import LogisticRegression ​ …

C嘎嘎入门篇:类和对象(1)

前言: 小编在之前讲述了C的部分入门基础,读者朋友一定要掌握好那些,因为C的学习和C有点不同,C的知识都是比较连贯的,所以我们学好了前面才可以学习后面的内容,本篇文章小编将会讲述C真正的入门篇&#xff1…

爬虫逆向学习(九):记录一个集cookie、请求参数、请求体、响应文本加密的站点反爬

此分享只用于学习用途,不作商业用途,若有冒犯,请联系处理 反爬前置信息 站点:aHR0cHM6Ly96d2Z3LmNxLmdvdi5jbi9pY2l0eS9pY2l0eS9lbmdpbmVlcmluZy9uYXZpZ2F0aW9u 接口:/icity/api-v2/cq.app.icity.engineering.Engine…

vue3组件通信(组合式API)

vue3组件通信(组合式API) vue3组件通信,采用组合式API。选项式API,参看官网 Vue3组件通信和Vue2的区别: 移出事件总线,使用mitt代替。 vuex换成了pinia。把.sync优化到了v-model里面了。把$listeners所…

fo-dicom开源库,深入理解项目的模块化设计

前言 DICOM(Digital Imaging and Communications in Medicine)是医学图像和相关信息的国际标准,广泛应用于医学影像领域。FO-DICOM是一个开源的DICOM库,提供了丰富的功能和模块,用于处理DICOM数据、实现DICOM网络通信…

16.面试算法-树的层次遍历与相关面试题

1. 树的层次遍历与相关面试题 1.1 层次遍历简介 广度优先在面试里出现的频率非常高,但是相对简单,题目也比较少,常见的题目也就七八道。 广度优先又叫层次遍历,基本过程如下: 层次遍历就是从根节点开始&#xff0c…

【STM32】 TCP/IP通信协议(1)

一、前言 TCP/IP是干啥的?它跟SPI、IIC、CAN有什么区别?它如何实现stm32的通讯?如何去配置?为了搞懂这些问题,查询资料可解决如下疑问: 1.为什么要用以太网通信? 以太网(Ethernet) 是指遵守 IEEE 802.3 …

【mbti课堂】计算机系统的六个层次与指令系统

课件:可以从 6 个层次分析和看待计算机系统的基本组成。 指令系统层处在硬件系统和软 件系统之间, 是硬、 软件之间的接口部分, 对两部分都有重要影响。 硬件系统用于实现每条指令的功能, 解决指令之间的衔接关系; 软件…

Golang | Leetcode Golang题解之第437题路径总和III

题目: 题解: func pathSum(root *TreeNode, targetSum int) (ans int) {preSum : map[int64]int{0: 1}var dfs func(*TreeNode, int64)dfs func(node *TreeNode, curr int64) {if node nil {return}curr int64(node.Val)ans preSum[curr-int64(targ…

复杂网络分析_NetworkX

一:NetworkX简介 NetworkX库是一个用于创建、操作复杂网络的结构、动态和功能的Python库。在经济网络中,它可以帮助分析各种经济实体(如公司、个人、国家)之间的相互关系和互动模式。以下是一些NetworkX在经济网络分析中的实际应…

ArrayList源码实现(一)

ArrayList源码实现(一) 1. ArrayList的大小是如何自动增加的? 初始化 在构造函数中,可以设定列表的初始值大小,如果没有的话默认使用,提供的静态数据 public ArrayList(int initialCapacity) {if (initi…

Milvus - 架构设计详解

Milvus 是一个专为在大规模密集向量数据集上进行相似性搜索而设计的开源向量数据库系统。其架构建立在流行的向量搜索库之上,如 Faiss、HNSW、DiskANN 和 SCANN,能够处理数百万、数十亿甚至数万亿的向量数据。为了全面了解 Milvus 架构,我们首…

计网作业3

1.交换机是依据 MAC地址 来转发数据包的 2.数据链路层 负责将数据封装成帧,在相邻节点间进行传输 数据链路层负责以下任务: 封装数据 物理地址寻址:使用MAC地址进行寻址,确保数据能够在局域网中正确传输到目标节点 介质访问控…

正确理解C++的友元friend

C的友元(friend)是个很重要的概念,该如何正确理解呢?本文将以友元函数为例讲解一下,仔细看。 友元的特性: 1、使用friend修饰的成员函数可以访问其他成员的私有成员(private)和保护成员(protected)。 2、…

快速上手基于Vue的动画引擎vueuse/motion

在现代前端开发中,动画可以极大地提升用户体验和界面美感。VueUse Motion 是一个强大的动画库,旨在为 Vue 应用提供简单易用的动画功能。那我们就来看看它在Vue项目中是如何应用的,快速手上为主,官网地址👇 vueuse/mo…

DevExpress WinForms中文教程:Data Grid - 如何添加或删除行?

本教程介绍DevExpress WinForm的Data Grid控件UI元素和API,它们使您和最终用户能够添加或删除数据行。您将首选学习如何启用内置的数据导航器,然后学习如何使用Microsoft Outlook启发的New Item行添加新记录。最后教程将向您展示基本的API,它…

全景可视化特点+可视化功能实现

全景可视化介绍 全景可视化是一种利用现代计算机技术、图像处理技术和虚拟现实技术,将现实世界中的场景以360度全景的方式呈现在用户面前的技术。它不仅能够提供水平方向360度的全景视野,还能通过垂直方向的视角变化,实现上下视角的调节&…

MVC core 、MVC framework addTagHelper、htmlhelper 、Environment

mvc core 标签助手 TagHelper 只有core 支持 htmlhelper mvc、mvc core 都支持 Environment <environment include"Development">*开发环境,使用不压缩的文件&#xff0c;排除压缩的文件*<link rel"stylesheet" asp-href-include"css/*"…

Linux相关概念和重要知识点(8)(操作系统、进程的概念)

1.操作系统&#xff08;OS&#xff09; &#xff08;1&#xff09;基本结构的认识 任何计算机系统都包含一个基本的程序集合&#xff0c;用于实现计算机最基本最底层的操作&#xff0c;这个软件称为操作系统。操作系统大部分使用C语言编写&#xff0c;少量使用汇编语言。 从…