前言:其实在我们的OC中以前是需要我们管理内存的但是现在的Xcode是不需要我们管理我们的内存的,但是我们还是有必要学习一下内存管理。这样会对我们对我们的内存有一个更加细致的了解
在说这个之前,说一下我们Xcode,现在我们的Xcode是无法让我们涉及内存管理的这样就不需要我们去操心我们的内存了,所以当你们在写我这上面的代码的时候,Xcode会一直报错的。关于我们Xcode中会有一个ARC帮助我们管理内存的
为什么有内存管理
管理范围:任何继承了NSObject的对象,对其他的基本数据类型无效
其实在我们的内存中分为两大块:
1、栈:用来存放一些基本数据类型
2、堆:用来存放我们的对象
例如下面的一段代码执行之后的内存情况如下:
这是我们的代码: 这就是我们的内存情况左边是我么的栈,右边是堆
上面可以反映出来我们的对象是被存储在堆里面。而我们的指针、变量存储在我们的栈里面;
当我们的代码执行完毕的时候,系统就会自动回收我们栈里面的所有东西,而我们的堆里面的东西则不会被回收,同样地我们的对象也不会被回收,如果我们想让我们的对象被回收,只有一种方法------>给我们的对象发送一条消息:哎!!!你被我回收了。赶紧让出储存空间来!!!
这条消息用我们的代码表示就是,调用我们对象其中的方法,我们的对象才会被回收
引用计数器
简介:
每一个OC对象都有一个引用计数器,是一个整数,用来表示对象被引用的次数(即是有多少其他对象在使用我们的对象)
我们的对象中的引用计数器中被引用的次数为0的时候,系统就会回收这个对象
当我们的对象被创建的时候他们的引用次数为1
引用计数器占用4个字节
release与retain的基本使用
一旦我们创建了一个对象,用了alloc方法就会导致我们的对象计数器的值为1,如果不减去,则会导致将来我们无法回收我们的对象
所以一旦调用了alloc必须调用release,有增必有减
使用方法:[Student retain];
这样我们的计数器加1,而:[Student release];就会让我们的对象计数器减1,
:查看我们的计数器的值:
我们的那个NSUInteger是我们long类型的基本数据,所以我们在打印的时候是用ld
野指针与空指针
野指针:指向僵尸对象的指针
空指针:里面存储的地址被清空的指针
僵尸对象:已经释放过内存的对象(在内存中找不到该对象)
对于初学者的一些常见错误:
计数器管理总结
多对象内存管理
简介:
当我们的对象变多的时候 例如:有一本书有很多人在用它,那么我们就需要将这个这个书的计数器值增加,当其中有人不使用这本书的时候,我们就需要让计数器减值,当没人使用这本书的时候,这本书也就会消失
所以:而当每一个人在使用这本书的时候就有必要使用上retain
当有人不需要这本书的时候就会使用上release直到这本书的计数器数值为0,即这本书的内存被释放
CF实例
相信有不少人都玩过CF,所以我就利用CF里面的一个创建房间的例子:
当我们创建一个房间然后让其他进来玩游戏的时候。
起初这个房间的计数器的值为1(因为你在这个房间里面),当又有一个人进入该房间的时候,我们就要让我们的房间对象计数器加1,这个时候房间的计数器的值就是2,当有16个人在这个房间里面那么这个房间的计数器的值就是16,而一旦有一个人离开这个房间的时候,我们就需要在这个人离开的时候对我们的房间计数器减1,最后房间只剩下你自己的时候,计数器就为1,最后连你也离开这个房间的时候,这个房间的计数器为0,就意味着这个房间被销毁
下面我们就研究如何让这个房间完成我们这个人来加1,人走减1的想法
代码演示:
以前我们在写我们的set方法的时候都是这样写的_book = book;
这种写法会带来很大的风险的
所以我们今天就开始这样写我们的代码:_book = [book retain];
一旦我们调用book这个对象的时候就需要加1 ,以防止接下来的一旦我们的书对象被[book release];时我们的Person不能使用这本书
而,一旦我们的Person被回收的时候如果不重写我们的dealloc
那么就会导致我们的book不能被回收
所以我们就需要在重写dealloc的时候也要减去先前我们在调用book时的加1,
而我们的代码格式如下:
注意几大原则:
set方法内存管理
基本实现:
补充:关于我们访问我们成员变量的方法:
关于我们set方法的使用原因:
我们创建一个Person对象,和两个车对象(c1.speed = 100 c2.speed = 200)
我们的人对象正在使用我们的c1这个车对象,现在挣得钱多了,想换一辆速度更快的车c2 但是在以前的代码中如果我们想换车,当我们人对象,换上我们的c2车的时候,c1车是不会消失的
那么就需要我们在换车的时候,就需要我们对c1做一次release操作
这个时候我们就需要利用set方法来帮助我们解决这个问题
这段代码中的if条件句的含义就是:当发现我们的现在所拥有的这两车不是我们想要的那辆,系统就执行下面的代码,而紧接着我们下一句代码的意思就是对我们现有的车c1座椅次release操作,第三句就是对我们的新车c2做一次retain操作
@property的内存管理
当然上面我们介绍了set方法其实在我们的代码编写的时候一般情况下我们基本上是不会用上面的那中方法,所以我们现在介绍一种我们在工作的时候经常用的写法:
我们的这一段代码与下面的代码作用是相同的
注意的是我们的dealloc还是要我们自己写上的
@property参数
同一类型的参数只能写一个不能多个写:例如@property(retain,assign)NSString*name
不同类型的参数可以写在一起
1、内存管理相关参数
a、retain:release旧值,retain新值(适用于OC对象)
b、assign:直接赋值(默认,适用于非OC对象类型)
c、copy:release旧值,retain新值
2、是否要生成set方法
readwrite:同时生成setter与getter的声明与实现(默认)
readonly:只会生成getter的声明与实现
3、多线程管理
a、nonatomic:性能高(一般就用这个)
b、atomic:性能低(默认)
4、setter与getter的名称
这个是我们系统帮助我们生成的set方法与get方法的代码:
所以以后我们就这样写我们的
总结:
网友评论