OC_内存管理(二)对象复制、循环引用问题、自动释放池
1.循环引用的问题
ClassA的头文件Class.h代码
- #import <Foundation/Foundation.h>
- //类的前向声明
- @class ClassB;
- //类的前向声明与包含头文件的区别?Q:
- @interface ClassA : NSObject
- //retain在ARC下面可以使用,但是最后使用strong
- @property(nonatomic,retain)ClassB *b;
- @end
- #import "ClassA.h"
- #import "ClassB.h"
- @implementation ClassA
- -(void)dealloc
- {
- NSLog(@"A的dealloc");
- [_b release];
- [super dealloc];
- }
- @end
ClassB的头文件ClassB.h代码:
- #import <Foundation/Foundation.h>
- @class ClassA;
- @interface ClassB : NSObject
- @property(nonatomic,retain)ClassA *a;
- @end
ClassB的实现文件ClassB.m代码:
- #import "ClassB.h"
- #import "ClassA.h"
- @implementation ClassB
- -(void)dealloc
- {
- NSLog(@"B的dealloc");
- [_a release];
- [super dealloc];
- }
- @end
接下来就是测试文件main.m代码:
- #import <Foundation/Foundation.h>
- #import "ClassA.h"
- #import "ClassB.h"
- int main(int argc, const char * argv[]) {
- @autoreleasepool {
- ClassA *a = [[ClassA alloc]init];
- ClassB *b = [[ClassB alloc]init];
- [a setB:b];
- [b setA:a];
- //获得所有权的是强引用
- /*因为对象a,对象b都是强引用,造成循环引用,无法正常释放。
- 解决方法:将其中一个改为弱引用。不获取对象所有权
- */
- [a release];
- [b release];
- }
- return 0;
- }
细心地同学会发现,在ClassA和ClassB的头文件中@property的属性这是均为retain,这表明都是强引用会获得对象所有权,这样就会使程序循环调用,而无法正常释放,解决方法为将二者之一的属性改为弱引用,比如改为assign。这样就无法获得对象所有权,从而能顺利解决循环调用问题。
一是import这两个被引用类的头文件,另一个是使用@class申明是类名,二者的区别:
1). import会包含这个类的所有信息,包括实体变量和方法,而@class只是告诉编译器,其后面声明的名称是类的名称,至于这些类是如何定义的,暂时不用考虑,后面会再告诉你;
2). 在头文件中,一般只需要知道被引用的类的名称就可以了,不需要知道其内部的实体变量和方法,所以在头文件中一般使用@class来声明这个名称是类的名称,而在类的实现部分,因为会用到这个引用类的内部的实体变量和方法,所以需要使用#import来包含这个被引用类的头文件。
3). 在编译效率方面考虑,如果你有100个头文件都#import了同一个头文件,或者这些文件是依次被引用的,如A–>B, B–>C, C–>D这样的引用关系。当最开始的那个头文件有变化的话,后面所有引用它的类都需要重新编译,如果你的类有很多的话,这将耗费大量的时间。而是用@class则不会。
4). 如果有循环依赖关系,如:A–>B, B–>A这样的相互依赖关系,如果使用#import来相互包含,那么就会出现编译错误,如果使用@class在两个类的头文件中相互声明,则不会有编译错误出现。
所以,一般来说,@class是放在interface中的,只是为了在interface中引用这个类,把这个类作为一个类型来用的。 在实现这个接口的实现类中,如果需要引用这个类的实体变量或者方法之类的,还是需要import在@class中声明的类进来.
对象复制:
1.创建一个新对象,新对象的内容和旧对象的内容是一样的。
2.给现有的对象发送copy消息,就可以复制出新的对象。
3.类中的对象类型实例变量,如果不想受外界影响,应该采用copy的方式复制出新的对象。
对象复制分为浅复制和深复制:
浅复制:复制对象时,如果对象中包含对象类型的实例变量,只复制指针值,新对象中的对象类型实例变量和旧对象中的对象类型实例变量指的是同一个对象。
深复制:复制对象时,如果对象中包含对象类型的实例变量,要对对象类型的实例变量也要做对象复制,新对象中的对象类型实例变量和旧对象中的对象类型实例变量指的是不同的对象。
复制对象有两种copy和mutableCopy:
2.mutableCopy复制出来的是可变对象;
自动释放池使用的五种方式
方式一:
- @autoreleasepool{
- Book *book = [Book alloc]initWithTitle:@“Object-C” andAuthor:@“Jobs” andPrice:23.90];
- [book print];
- }
方式二:
- NSAutoreleasePool *pool = [NSAutoreleasePool new];
- Book *book = [Book alloc]initWithTitle:@“Object-C” andAuthor:@“Jobs” andPrice:23.90];
- [book print];
- [pool drain]; //等效于[pool release];
方式三:
- @autoreleasepool
- {
- Book *book = [Book alloc]initWithTitle:@“Object-C” andAuthor:@“Jobs” andPrice:23.90];
- [book print];
- @autoreleasepool
- {
- Book *book = [Book alloc]initWithTitle:@“Object-C” andAuthor:@“Jobs” andPrice:23.90];
- [book print];
- }
- }
方式四
- @autoreleaspool
- {
- for(int i = 0;i < 10000;i++)
- {
- @autoreleasepool
- {
- Book *book = [Book bookWithTitle:[NSString stringWithFormat:@“book%d”,i+1] andAuthor:[NSString stringWithFormat:@“author%d”,i+1] andPrice:20+i];
- [book print];
- }
- }
- }
方式五:
- @autoreleasepool
- {
- NSMutableString *str = [NSMutableString stringWithString:@“hello world”];
- NSLog(@“%@“,str);
- /*凡是不通过new、alloc、copy创建的对象都不拥有对象所有权,这种创建的对象会自动加入自动释放池,由自动释放池进行延迟释放*/
- }
下面对自动释放池的使用进行了总结:
1.在自动释放池结束时会给每个管理的对象发送一次release消息
2.[book release]的作用是将对象加入自动释放池
3.在OC的内置类(NSString、NSArray等)中提供的类方法创建的对象实例都是(延迟释放对象),也就是在对象创建完成后将对象加入自动释放池,这种对象不需要我们去发release消息释放。(方法五)
4.自动释放池是可以嵌套使用的,对象在加入自动释放池时,选择离它最近的释放池,就近原则,(好聪明啊!都知道懒省事),目的是为了让延迟释放的对象,尽快得到释放,降低程序期间内存的占用。(方式3)
5.当程序中出现大量创建延迟释放对象的代码时,最好给它加一个独立的自动释放池,保证这些对象在不使用时立刻释放掉(方法四)
浅 复 制:在复制操作时,对于被复制的对象的每一层复制都是指针复制。
深 复 制:在复制操作时,对于被复制的对象至少有一层复制是对象复制。
完全复制:在复制操作时,对于被复制的对象的每一层复制都是对象复制。
1、在复制操作时,对于对象有n层是对象复制,我们可称作n级深复制,此处n应大于等于1。
2、对于完全复制如何实现(目前通用的办法是:迭代法和归档),这里后续是否添加视情况而定,暂时不做讲解。
3、指针复制俗称指针拷贝,对象复制也俗称内容拷贝。
4、一般来讲,
浅层复制:复制引用对象的指针。
深层复制:复制引用对象内容。
retain:始终是浅复制。引用计数每次加一。返回对象是否可变与被复制的对象保持一致。
copy:对于可变对象为深复制,引用计数不改变;对于不可变对象是浅复制,引用计数每次加一。始终返回一个不可变对象。
mutableCopy:始终是深复制,引用计数不改变。始终返回一个可变对象。
不可变对象:值发生改变,其内存首地址随之改变。
可变对象:无论值是否改变,其内存首地址都不随之改变。
引用计数:为了让使用者清楚的知道,该对象有多少个拥有者(即有多少个指针指向同一内存地址)。
转载于:https://www.cnblogs.com/xjf125/p/4730495.html
OC_内存管理(二)对象复制、循环引用问题、自动释放池相关推荐
- 【iOS高级资深工程师面试篇】④、2022年,金九银十我为你准备了《iOS高级资深工程师面试知识总结》 内存管理部分2/2 引用计数-弱引用-自动释放池-循环引用
iOS高级资深工程师面试篇系列 - 已更新3篇 UI部分1/3 -UITableView-事件传递&视图响应 UI部分2/3 -图像显示原理-UI卡顿&掉帧 UI部分3/3 -UIVi ...
- python 引用计数 循环引用_Python对象的循环引用问题
Python对象循环引用 我们来介绍一下 Python 是采用何种途径解决循环引用问题的. 循环引用垃圾回收算法 上图中,表示的是对象之间的引用关系,从自对象指向他对象的引用用黑色箭头表示.每个对象里 ...
- 内存管理-定时器循环、内存布局、tagged pointer、weak指针、copy、自动释放池
先上代码,我们平时用的定时器,cadisplaylink.nstimer,CADisplayLink.NSTimer会对target产生强引用,如果target又对它们产生强引用,那么就会引发循环引用 ...
- 【深入Cocos2d-x】探索Cocos2d-x中的内存管理-引用计数和自动释放池
2019独角兽企业重金招聘Python工程师标准>>> #深入Cocos2d-x-探索Cocos2d-x中的内存管理-引用计数和自动释放池 ###引用计数(Reference Cou ...
- iOS内存管理 —— 自动释放池和runloop
iOS内存管理 -- 自动释放池和runloop 1. 自动释放池 1.1 自动释放池介绍 1.2 自动释放池底层原理 objc_autoreleasePoolPush autoreleaseNoPa ...
- 第六讲:Obj-C 内存管理4 - 自动释放池
转:http://tigercat1977.blog.163.com/blog/static/2141561122012111294616203/ 第六讲:Obj-C 内存管理4 - 自动释放池 主要 ...
- iOS中内存自动释放池
自动释放池 iOS应用的主线程在每次runloop开始的时候创建自动释放池,在runloop结束的时候释放自动释放池.如果在一个runloop内,应用程序创建了大量临时对象,自动释放池可以减少内存峰值 ...
- JVM自动内存管理:对象判定和回收算法
可回收对象的判断方法 1.引用计数算法 2.可达性分析算法 引用计数算法 给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1:当引用失效时,计数器值就减1:任何时刻计数器为0的对象就是 ...
- 操作系统概念学习笔记 16 内存管理(二) 段页
操作系统概念学习笔记 16 内存管理 (二) 分页(paging) 分页(paging)内存管理方案允许进程的物理地址空间可以使非连续的.分页避免了将不同大小的内存块匹配到交换空间上(前面叙述的内存管 ...
- 内存管理(二) - MRC关键字解读
本篇主要学习以下几个知识点 alloc/reatin/release/dealloc 理解 autorelease 理解 autorelease GUN 实现 autorelease 苹果 实现 原文 ...
最新文章
- Idea不能新建package的解决
- Linux(debian)的网络内核参数优化来提高服务器并发处理能力
- python的用途实例-Python基础之函数原理与应用实例详解
- CentOS 初体验十七:Nexus发布仓库和引用
- 什么是 C 和 C ++ 标准库?
- Maven +Tomcat+m2eclipse的热部署(hot deploy)
- matlab编写信号采集程序,MATLAB语音信号采集课程设计
- Mininet的内部实现原理简介
- C语言基础专题 - 指针(编写中)
- MySQL-JDBC
- 虚拟服务器软件,VMware ESXi(服务器虚拟化软件) V7.0 官方版
- 中国知名个人站长排行TOP91
- 阿里巴巴牵手福特 共同打造智联网汽车
- 如何修改服务器的dns,如何修改服务器dns地址
- 7z文件格式及其源码的分析(四)
- 龙芯与飞腾roadmap
- 如何实现vue表单验证cron表达式?【亲测有效】
- 余弦定理对比文本相似度实现查重
- loaderruner
- 根据AD账号直接单点登录到第三方系统
热门文章
- 用eclipse无法打开html里用绝对路径添加的图片但是在外面可以打开的解决方法
- java实现调查问卷_jsp70516调查问卷自动生成与分析系统 双数据库 mysql版
- 深度学习框架PyTorch:入门与实践 学习(四)
- 推荐给初学LSTM或者懂个大概却不完全懂的人
- 使用Gotestwaf测试WAF检测能力
- Modbus PLC攻击分析:Smod渗透框架研究
- 浅谈MySQL存储引擎
- 我在使用Spring Gateway时遇到的一些坑
- 第 7 章 Neutron - 066 - Neutron 网络基本概念
- npm i 报错 'match' of undefined 错误以及删除node_modules失败