ARC机制

2024-05-29 04:08
文章标签 机制 arc

本文主要是介绍ARC机制,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


一、ARC简介

ARC是自iOS 5之后增加的新特性,完全消除了手动管理内存的烦琐,编译器会自动在适当的地方插入适当的

retain、release、autorelease语句。开发者不再需要担心内存管理,因为编译器为你处理了一切

ARC 是编译器特性,而不是 iOS 运行时特性,它也不是类似于其它语言中的垃圾收集器。因此 ARC 和手动内

存管理性能是一样的,有时还能更加快速,因为编译器还可以执行某些优化

二、ARC原理

1、编译器如何自动管理内存

Clang编译器项目自带一个“静态分析器”,用于志明程序里应用计数出问题的地方,比如有Person类中有一个类方法

if(self == [Person Class])
{Person *p = [[self alloc] init];NSLog(@"%@",p);
}
else
{NSLog(@"%@是Person的子类",self);
}

由于if语句之外无法引用p,如果没有使用ARC机制,这段代码就会有内存泄漏,此时p对象内存中的计数器值为

1,因为没有相关语句来释放,所以这个对象会一直占据着它所在的内存空间。判定内存是否泄漏所用的规则很简

明:调用Person的alloc方法所返回的p对象的保留计数比期望值要多1,之后却没有与之对应的释放操作来抵消,计算

机可以将这些规则套用在程序上,从而分析出有内存泄漏问题的对象,“静态分析器”还可以根据需要,预先加入适当

的retain或release操作以避免内存泄漏的问题,自动引用计数正是源自于此。于是在前面那段代码的if语句结束之前,

可以于对象p上自动执行release操作,也就是把代码自动改写成以下形式:

if(self == [Person Class])
{Person *p = [[self alloc] init];NSLog(@"%@",p);[p release];
}
else
{NSLog(@"%@是Person的子类",self);
}

2、ARC对代码的优化

在编译期,ARC会把能够互相抵消的retain、release和autorelease操作约简,如果发现在同一个对象上执行了多

次保留和释放操作,那么ARC有时可以成对地移除这两个操作。比如有些方法在返回对象前执行了autorelease操作,

而调用方法地代码可能需要将返回地对象保留,例如在非ARC环境下有个初始化Person的类方法

+ (id)personWithAge:(int)age
{Person *p = [[[self alloc] init] autorelease];p.age = age;return p;
}>

假如当某个类里有个Person类的强引用成员变量_myPerson,当初始化该类时就可以有

<span style="font-size:18px;">_myPerson = [Person PersonWithAge:10];</span>

调用personWithAge方法会返回新的Person对象,而此方法在返回对象之前为其调用了autorelease方法,由于实例变

量_myPerson是个强引用,所以编译器在设置其值的时候还需要执行一次保留操作,因此,上面那句代码等价于下面

这段手工管理引用计数代码

Person *p = [Person personWithAge:10];
_myPerson = [p retain];


或者可以设想以下,当_myPerson = [p retain]该语句不执行retain操作,也就是直接_myPerson = p,那么当自动释放

池回收对象时,p对象的引用计数值刚好执行完release之后降为0,那么该内存对象就会被回收,而_myPerson就会指

向一个僵尸对象。

此时应该能看出personWithAge方法里的autorelease和上段代码中的retain操作时多余的,为提升性能,可以将

二者删去。

当ARC在运行期检测到这一对多余的操作时,也就是autorelease其后紧跟着retain,为了优化代码,在方法中返

回自动释放的对象时会执行一个特殊的函数,此时不直接调用对象的autorelease方法,而改为调用

objc_autoreleaseReturnValue。此函数会检视当前方法返回之后即将要执行的那段代码,若发现那段代码要在返回的

对象上执行retain操作,则设置全局数据结构中的一个标志位,而不执行autorelease操作。与之相似,如果方法返回

了一个自动释放的对象,而调用方法的代码要保留此对象,那么此时不执行retain,而是执行

objc_retainAutoreleaseReturnValue函数,此函数要检测刚才提到的那个标志位,若已置位,则不执行retain操作,设

置并检测标志位要比autorelease和retain更快。下面这段代码演示类ARC是如何优化程序的

在ARC编译环境下,对于Person类中的初始化的类方法

+ (id)personWithAge:(int)age
{Person *p = [[[self alloc] init] autorelease];p.age = age;objc_autoreleaseReturnValue(p);
}
而使用该方法时

<span style="font-size:18px;">Person *p = [Person personWithAge:10];
_myPerson = objc_retainAutoreleaseReturnValue(p);</span>

为了得到最佳效率,这些特殊函数得实现代码都会因处理器而异,下面得伪代码演示了这一步骤

id objc_autoreleaseReturnValue(id object)
{if(/*后面的代码有一次retain操作*/){set_flag(object);return object;		// 不会再进行autorelease操作}else{return [object autorelease];}
}id objc_retainAutoreleaseReturnValue(id object)
{if(get_flag(object))		// 即该retain操作前有autorelease{clear_flag(object);return object;		// 不再进行retain操作}else{return [object retain];}
}


objc_autoreleaseReturnValue函数是如何检测方法调用者是否会立刻retain对象呢,这要根据处理器来决定,也就是

只有编译器的开发者能实现此函数了。

三、ARC的使用

1、规则

ARC的规则非常简单,只要还有一个强指针指向对象,对象就会保持再内存中。

2、强指针和弱指针

默认所有实例变量和局部变量都是强指针;

弱指针指向的对象被回收后,弱指针会自动变成nil指针,不会引发野指针错误

3、使用注意

(1)不能调用release、retain、autorelease、retainCount、copy
(2)可以重写dealloc,但是不能调用[super dealloc]
(3)@property : 想长期拥有某个对象,应该用strong,其他对象用weak
(4)其他基本数据类型依然用assign
(5)两端互相引用时,一端用strong、一端用weak


代码示例:

	
#import <Foundation/Foundation.h>
@class Person;@interface Dog : NSObject
//谨记:@property后面跟着分号;
@property (nonatomic,strong) Person *person;
@end#import "Dog.h"@implementation Dog
- (void)dealloc
{NSLog(@"Dog is dealloc");// [super dealloc]; 不需要再调用了}
@end/*strong:表示该变量引用的是强指针(默认)weak:表示该变量引用的是弱指针(多用于对象循环引用)*/#import "Person.h"
//谨记:@class 类名;,后面跟分号;
@class Dog;@interface Person : NSObject@property (nonatomic,assign) int age;
//强指针类型
//@property (nonatomic,strong) Dog *dog;
//使用弱指针,当main函数执行完会先回收局部变量,因为指向够的指针是弱指针,所以狗对象会被释放,狗对象被释放之后里面的成员变量person也不存在了所以就不会指向person,所以person也会被释放
@property (nonatomic,weak) Dog *dog;@end#import "Person.h"@implementation Person
- (void) dealloc
{NSLog(@"age = %d Person---dealloc",_age);
}
@end/*指针:强指针:默认情况下,所有指针都是强指针 __strong弱指针:__weak,弱指针指向的对象会被回收*/
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Dog.h"
int main()
{Person *p = [[Person alloc] init];Dog *d = [[Dog alloc] init];p.age = 10;/*当两个成员变量都是强指针且循环引用,则两个强指针一直互相指向则arc机制不会释放对象。p.dog = d;d.person = p;*/return 0;
}


这篇关于ARC机制的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1012605

相关文章

Redis客户端连接机制的实现方案

《Redis客户端连接机制的实现方案》本文主要介绍了Redis客户端连接机制的实现方案,包括事件驱动模型、非阻塞I/O处理、连接池应用及配置优化,具有一定的参考价值,感兴趣的可以了解一下... 目录1. Redis连接模型概述2. 连接建立过程详解2.1 连php接初始化流程2.2 关键配置参数3. 最大连

Spring Security 单点登录与自动登录机制的实现原理

《SpringSecurity单点登录与自动登录机制的实现原理》本文探讨SpringSecurity实现单点登录(SSO)与自动登录机制,涵盖JWT跨系统认证、RememberMe持久化Token... 目录一、核心概念解析1.1 单点登录(SSO)1.2 自动登录(Remember Me)二、代码分析三、

Go语言并发之通知退出机制的实现

《Go语言并发之通知退出机制的实现》本文主要介绍了Go语言并发之通知退出机制的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录1、通知退出机制1.1 进程/main函数退出1.2 通过channel退出1.3 通过cont

Spring Boot 中的默认异常处理机制及执行流程

《SpringBoot中的默认异常处理机制及执行流程》SpringBoot内置BasicErrorController,自动处理异常并生成HTML/JSON响应,支持自定义错误路径、配置及扩展,如... 目录Spring Boot 异常处理机制详解默认错误页面功能自动异常转换机制错误属性配置选项默认错误处理

Java中的xxl-job调度器线程池工作机制

《Java中的xxl-job调度器线程池工作机制》xxl-job通过快慢线程池分离短时与长时任务,动态降级超时任务至慢池,结合异步触发和资源隔离机制,提升高频调度的性能与稳定性,支撑高并发场景下的可靠... 目录⚙️ 一、调度器线程池的核心设计 二、线程池的工作流程 三、线程池配置参数与优化 四、总结:线程

Android ClassLoader加载机制详解

《AndroidClassLoader加载机制详解》Android的ClassLoader负责加载.dex文件,基于双亲委派模型,支持热修复和插件化,需注意类冲突、内存泄漏和兼容性问题,本文给大家介... 目录一、ClassLoader概述1.1 类加载的基本概念1.2 android与Java Class

Spring事务传播机制最佳实践

《Spring事务传播机制最佳实践》Spring的事务传播机制为我们提供了优雅的解决方案,本文将带您深入理解这一机制,掌握不同场景下的最佳实践,感兴趣的朋友一起看看吧... 目录1. 什么是事务传播行为2. Spring支持的七种事务传播行为2.1 REQUIRED(默认)2.2 SUPPORTS2

MySQL中的锁机制详解之全局锁,表级锁,行级锁

《MySQL中的锁机制详解之全局锁,表级锁,行级锁》MySQL锁机制通过全局、表级、行级锁控制并发,保障数据一致性与隔离性,全局锁适用于全库备份,表级锁适合读多写少场景,行级锁(InnoDB)实现高并... 目录一、锁机制基础:从并发问题到锁分类1.1 并发访问的三大问题1.2 锁的核心作用1.3 锁粒度分

Redis的持久化之RDB和AOF机制详解

《Redis的持久化之RDB和AOF机制详解》:本文主要介绍Redis的持久化之RDB和AOF机制,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录概述RDB(Redis Database)核心原理触发方式手动触发自动触发AOF(Append-Only File)核

PostgreSQL中MVCC 机制的实现

《PostgreSQL中MVCC机制的实现》本文主要介绍了PostgreSQL中MVCC机制的实现,通过多版本数据存储、快照隔离和事务ID管理实现高并发读写,具有一定的参考价值,感兴趣的可以了解一下... 目录一 MVCC 基本原理python1.1 MVCC 核心概念1.2 与传统锁机制对比二 Postg