内存管理Memory OC——第九天
内存管理方式
垃圾回收机制:(Garbage
Collection),有系统管理内存,开发人员需要管理
注:OC从2.0之后就开始支持垃圾回收机制,但是只适用于OS开发,(苹果电脑的操作系统),我们iOS平台是不支持垃圾回收机制;(面试题)
不支持垃圾回收机制,OC是如何管理内存的呢?
//内存不释放
就叫内存泄露

|
图中那个的行为
|
OC中操作 |
OC中方法
|
|
根据照明设备所做的动作
|
对对象的操作
|
|
|
开灯
|
生成对象
|
alloc/copy/new
|
|
需要照明
|
持有对象
|
return
|
|
不需要照明
|
释放对象
|
release/autorelese(不会立即释放且与@autoreleasepool配合使用)
|
|
关灯
|
废弃对象
|
dealloc
|
//图中需要照明的人数,就代表引用计数
//1.当第一人"需要照明",引用计数+1
有0-->1
//2.当第二个人"需要照明",引用计数+1
有1-->2
//3.当第二个人"需要照明",引用计数+1
有2-->3
//4.当有一个人"不需要照明",引用计数-1
有3-->2
//5.当再有一个人"不需要照明",引用计数-1
有2-->1
//6.当再有一个人"不需要照明",引用计数-1
有1-->0
1.MRC:(Manual Reference
Counting),手动引入计数器,有开发人员通过手动引入计数器来管理内存。
2.ARC:(Automatic Reference
Counting),自动引入计数器,由系统通过引入计数器管理内存
//学习好MRC是为了更好使用ARC,iOS5.0之后就有了ARC;
1.如果工程环境是ARC,而部分文件使用了MRC,使用一个参数
-fno-objc-arc
2.如果工程环境是MRC,而部分文件使用了ARC,使用一个参数
-fobjc-arc
Person
: NSObject
(nonatomic,copy)NSString
*name;
Person
//dealloc
方法是对象被销毁的时候自动调用的方法,不需要手动调用,由于dealloc方法是重写的父类,所以重写此方法的时候,一定要把父类的方法内容也写上
(void)dealloc
NSLog(@"Person%@对象被销毁了",_name);
//以后重写dealloc方法时一定调用[super
dealloc]; 且此方法一定要写在最下面
[super
dealloc];
*p
= [[Person
alloc]init];//alloc会造成对象的引用计数器由0-->1
p.name
=
@"缓缓";
//如何判断一个对象是否被持有,就看它的引用计数
//retainCount
:对象的引用计数
NSLog(@"%lu",p.retainCount);
//计数器为1
//如果自己创建的对象不使用时,释放对象,使用release
[p release];
//
NSLog(@"%lu",p.retainCount);
对象死了就不能再使用它了
[p
release];
不要过度释放,也等于操作僵尸对象
*p2 =
[[Person
alloc]init];
//0--->1
p2.name
=
@"武媚娘";
+1
//非自己创建的对象,自己也能持有
p2 = [p2 retain];
//由1--->2
NSLog(@"%lu",p2.retainCount);
//非自己创建的对象,自己也能持有
Person
*p3 =
[p2 retain];
NSLog(@"%lu",p3.retainCount);
//2--->3
[p2 release];//3-->2
[p2 release];//2-->1
[p3 release];//1-->0
Person
*p4 =
[[Person
alloc]init];
p4.name
=
@"小骨";
[p4 retain];//2
[p4 retain];//3
[p4 retain];//4
[p4 release];//3
[p4 release];//2
[p4 release];//1
[p4 release];//0
[p4
retain];//人死不能复生,对象死也不能复生
1.retain :
计算器 +1 ,会返回对象本身;(返回值为id泛类型)
2.release : 计数器 -
1,没有返回值
3.retainCount
的作用:获取当前对象的计数器数值
4.dealloc
当一个对象被销毁的时候,系统会自动调用,再次方法中一定要调用[super
delloc];且这句话要放到最后;
//僵尸对象:所占内存被回收的对象,就叫僵尸对象,僵尸对象不能再使用
//野指针:指僵尸对象的指针就叫野指针
//空指针:没有志向任何东西的指针就叫空指针叫空指针,(nil,NULL,0),给空指针发送消息
//
alloc 对应
dealloc
//
retain 对应 release
区别: [[Person
alloc]init]; 内存永远不会被释放
//
[[[Person alloc]init]release];
创建的同时立即就被释放掉
//autorelease 相比
release,也能造成引用计数器-1,不过autorelease
不是立即-1,会在未来某段时间做-1操作;
操作,这个对象的引用计数器不会立即减1,如果把这个autorelease
操作放到自动释放出中,会在出池子的一瞬间减1,如果你没有放到池子中,不会对autorelease
操作对象进行减1;
必须和自动释放池配合使用
Person *p5 = [[Person alloc]init];//0--->1
[p5 autorelease];//1
NSLog(@"%lu",p5.retainCount);
//第一种形式
NSAutoreleasePool
自动释放池类
*pool =
[[NSAutoreleasePool
alloc]init];
Person
*p6 =
[[Person
alloc]init];
p6.name
=
@"白子画";
[p6 autorelease];//或者用[p6
release];
NSLog(@"%lu",p6.retainCount);
[pool release];
//第二种形式
@autoreleasepool
{
Person
*p7 =
[[Person
alloc]init];
p7.name
=
@"糖宝";
[p7 autorelease];//未来的时间减1,出自动释放池减1
//
[p7 release];//-1
//过度释放
NSLog(@"%lu",p7.retainCount);
}//此时也会引起过度释放,是由autorelease引起的
//水污染谁治理,谁alloc谁release,谁return谁release,autorelease
//你想占用某个对象,就应该让对象的计数+1,(也就是让对象做以retain操作)
//当你不想持有(占有)某个对象时,就应该让对象的引用计数-1,(也就是让对象做一release操作)
nil;
Person
*p8 =
[[Person
alloc]init];
p8.name
=
@"紫熏";
Person
*p9 =
[p8 retain];
kRelease_Safe(p8);
NSLog(@"%@",p9.name);
kRelease_Safe(p9);
[p8 release];//对一个空指针发送消息,没有任何影响
*mArray =
[[NSMutableArray
alloc]initWithCapacity:0];
//向数组中添加十个人
for
(int
i
= 0;
i < 10
;
i ++) {
Person
*person =
[[Person
alloc]init];
person.name
=
[NSString
stringWithFormat:@"%d",i];
//数组在添加元素的时候,会对添加的元素做一次retain操作
[mArray addObject:person];
kRelease_Safe(person);
}
NSLog(@"%@",mArray);
//数组在释放自己之前,会对之前添加到数组中的元素进行引用计数减1的操作
kRelease_Safe(mArray);
//此时我们没有alloc
也没有retain ,所以不需要对数组mArray2 的内存释放负责
NSMutableArray
*mArray2 =
[NSMutableArray
array];//
Person
*p10 =
[[Person
alloc]init];
p10.name
=
@"朱然";
[mArray2 addObject:p10];
kRelease_Safe(p10);
NSString
*string =
[[NSString
alloc]initWithString:@"12345678912345"];
NSLog(@"%ld",string.retainCount);
//使用其他方法创建的字符串都在常量区
NSString
*string2 =
[NSString
stringWithFormat:@"1234567890"];
NSLog(@"%lu",string2.retainCount);
//没人去释放字符串,stringWithFormat:
计数器1,其他计数为-1;
对象能够使用copy操作的前提是,此类必须遵循NSCopying 协议
//浅拷贝,只拷贝地址,同时对象的引用计数+1;此时拷贝出来的对象原对象的所占的空间大小相等,内容也相等
//深拷贝
不止拷贝空间和内容,而且从新开辟了一块内存
Person
: NSObject<</span>NSCopying>必须遵循NSCopying
协议
(nonatomic,copy)NSString
*name;
(void)dealloc{
[super
dealloc];
(id)copyWithZone:(NSZone
*)zone{
//返回对象的时候要做一次retain操作,外界的接受者才持有这个对象
retain];
返回的是新的对象,此时两个对象所占的空间大小相同,内容也相同
Person
*p
= [[Person
allocWithZone:zone]init];
p.name
=
self.name;
return
p;
Person
*p11 =
[[Person
alloc]init];
p11.name
=
@"笙萧默";
Person
*p12 =
[p11 copy];
NSLog(@"%@",p12.name);
NSLog(@"p11
= %p p12 = %p ",p11,p12);
kRelease_Safe(p11);
kRelease_Safe(p12);
申请创建对象的同时让其引用计数0-—>1(不常用)
//new其实就做了alloc和init
两步操作,申请空间并初始化
//
[Person new] = [Person alloc]init];
Person
*p13 =
[Person
new];
p13.name
=
@"东方";
kRelease_Safe(p13);
1.引用计数+1(alloc ,copy , new , retain)
2.引用计数 -1 (release , autorelease)
3.要想内存不出现泄漏,引用计数-1的次数相等
4.一旦引用计数为0的时候系统会自动调用dealloc 方法
5.谁污染谁治理,谁alloc谁release,谁return谁release,autorelease
内存管理Memory OC——第九天的更多相关文章
- Android 内存管理 &Memory Leak & OOM 分析
转载博客:http://blog.csdn.net/vshuang/article/details/39647167 1.Android 进程管理&内存 Android主要应用在嵌入式设备当中 ...
- SQL Server 2012 内存管理 (memory management) 改进
SQL Server 2012 的内存管理和以前的版本相比,有以下的一些变化. 一.内存分配器的变化 SQL Server 2012以前的版本,比如SQL Server 2008 R2等, 有sing ...
- 内存管理 - MEMORY POOL
内存池优势: 效率高,频繁的new和delete效率低下 减少内存碎片,反复向系统申请和释放内存会产生大量内存碎片 防止内存泄露 内存池设计思路: 内存池可以根据实际需要,设计成不同的样子.下面是针对 ...
- QF——OC内存管理详解
堆的内存管理: 我们所说的内存管理,其实就是堆的内存管理.因为栈的内存会自动回收,堆的内存需要我们手动回收. 栈中一般存储的是基本数据类型变量和指向对象的指针(对象的引用),而真实的对象存储在堆中.因 ...
- oc 第五天(内存管理)
OC的重点: 内存管理 1 基本原理 OC的内存回收机制是和JAVA的自动回收机制是不同的,它有两种模式,或者准确的说是同 一种模式的两种不同体现,下面简单总结下. 1手动内存回收 ...
- OC开发系列-内存管理
概述 移动设备的内存极其有限,每个app所有占用的内存是有限的.当app所占用的内存比较多时,系统会发出内存警告,这时得回收一些不需要再使用的内存空间. 任何集成了NSObject的对象都需要手动进行 ...
- Object-c 内存管理
内存管理 主要内容 1.内存管理的概念 2.引用计数 3.如何持有对象所有权 4.自动释放池 5.@property的使用 什么是内存管理 内存管理是关于如何管理对象生 ...
- C++中的内存管理
在C++中也是少不了对内存的管理,在C++中只要有new的地方,在写代码的时候都要想着delete. new分配的时堆内存,在函数结束的时候不会自动释放,如果不delete我分配的堆内存,则会造成内存 ...
- OC内存管理(MRC)
首先说明一下几块存储区域: 栈区(局部变量.函数参数值) 堆区(对象.手动申请/释放内存) BSS区(未初始化的全局变量.未初始化的静态数据) 常量区(字符串常量以及初始化后的全局变量.初始化后的静态 ...
随机推荐
- Swift 3.0项目迁移的一些记录
刚执行完Convert后报错600+,真是令人奔溃. 之后重新编译,仔细分析后发现其实真实错误远没有那么多.最终实际修改到的错误也就几十个,而且其中某些还是同一种错误. 这个项目是一个供自己使用的浏览 ...
- jQuery 效果 – 隐藏和显示
在 jQuery 中可以使用 hide() 和 show() 方法来隐藏和显示 HTML 元素,以及使用 toggle() 方法能够切换 hide() 和 show() 方法. 隐藏.显示.切换,滑动 ...
- Mysql 统一设置utf8字符
无聊的关于有效配置文件路径的备忘 原来阿里云服务器的mysql 5.5 , 配置/etc/my.cnf是没有任何作用的,需要编辑/etc/mysql/my.cnf 妈的, 就是这一点让我测试了两天, ...
- Redis之(三)管理命令
4.1键管理 通过学习五种数据类型的操作命令,可以发现,Redis对每种数据的处理之前,都要先指定该数据的key,然后再指定对该数据进行何种操作. Redis中的key有点类似于Java中的变量名,起 ...
- proc文件系统探索 之 根目录下的文件[二]
包括对proc根目录下stat,uptime,swaps三个文件的解析. /proc/stat 文件包含了系统启动后的一些系统统计信息. Cat /proc/stat: cpu 77781 1077 ...
- JAVA通过继承Thread来创建线程
创建一个线程的第二种方法是创建一个新的类,该类继承Thread类,然后创建一个该类的实例. 继承类必须重写run()方法,该方法是新线程的入口点.它也必须调用start()方法才能执行. 实例 // ...
- PHP学习(3)—在HTML中嵌入PHP
我们以一个提交订单和显示订单信息的例子为学习PHP的开始.这个例子包含两个文件.一个提交订单的html文件:orderform.html,一个显示订单信息的php文件:processorder.php ...
- Xcode7.3.1中通过最新的CocoaPod安装pop动画引擎
CocoaPod是一个用ruby实现,用于方便的管理Xcode中第三方插件的管理器.用它我们可以很方便的安装和升级插件而不用担心破坏原有的项目. 而pop是一个用于实现App中动画的引擎,它是由Fac ...
- Retrofit 2.0 超能实践(四),完成大文件断点下载
作者:码小白 文/CSDN 博客 本文出自:http://blog.csdn.net/sk719887916/article/details/51988507 码小白 通过前几篇系统的介绍和综合运用, ...
- SSO 基于Cookie+fliter实现单点登录 实例解析(一)
接上文,SSO的理论讲解,接下来实践实践! 1.使用Cookie解决单点登录 技术点: 1.设置Cookie的路径为setPath("/").即Tomcat的目录下都有效 2.设置 ...