常用术语解释
1.为什么要进行内存管理
(1)大家都知道苹果的手机即使512运行也很流畅,关键在于苹果的软件对内存管理的严谨,这也是oc的一个特色之处。我们程序员在开发中更得注意内存的管理,以免内存泄漏,下面说一些有关内存管理的知识。
(2)任何继承了NSObject的对象,都需要内存管理,因为这些系统不会自动回收
(3)对其他数据类型(int,char,float,double,struct,enum),不需要内存管理,因为这个数据类型系统会自己回收。
2.计数器。在oc中会对对象的使用情况有个记录,这就是计数器的概念。
(1)retain :计数器+1,会返回对象本身
(2) release :计数器-1,没有返回值
(3) retainCount :获取当前的计数器
(4)alloc
(5)当使用alloc、new或者copy创建一个新对象时,新对象的引用计数器默认就是1
(6)当一个对象的引用计数器值为0时,对象占用的内存就会被系统回收。换句话说,如果对象的计数器不为0,那么在整个程序运行过程,它占用的内存就不可能被回收,除非整个程序已经退出
* 当一个对象要被回收的时候,就会调用
* 一定要调用[super dealloc],这句调用要放在最后。
3.对象的销毁
(1)当一个对象的引用计数器值为0时,那么它将被销毁,其占用的内存被系统回收
(2)当一个对象被销毁时,系统会自动向对象发送一条dealloc消息
(3) 一般会重写dealloc方法,在这里释放相关资源,dealloc就像对象的遗言
(4) 一旦重写了dealloc方法,就必须调用[super dealloc],并且放在最后面调用
不要直接调用dealloc方法
(5) 一旦对象被回收了,它占用的内存就不再可用,坚持使用会导致程序崩溃(野指针错误)
4.野指针
“野指针”不是NULL指针,是指向被释放的或者访问受限的垃圾内存的指针。
内存管理原则
(1)谁创建,谁release
(3)谁retain,谁release
(4)只要你调用了retain,无论这个对象是如何生成的,就调用release或者autorelease。
总之一个原则,只要retain了就得release。只要有让计数器加一的操作,就必须得有使计数器减一的操作。
set方法的内存管理
- (void)setCar:(Car *)Car
{
if( Car !=_Car)// 先判断是不是新传进来的对象
{
[_Car release];// 既然有了新的对象,就需要释放原先的对象
_Car = [Car retain]; // 新对象做一次retain,是计数器加1
}
}
由于做了一次retain操作,所以应该使用地dealloc进行释放,
1.一定要[super dealloc],而且要放在最后面
2.对self(当前)所拥有的其他对象做一次release。
- (void)dealloc
{
[_Car realease];// 这个类中所有对象成员变量都需要做一次release
[super dealloc];后面必须调用父类的dealloc方法
}
总之把我一下几个原则:
(1)使用(占用)某个对象,就应该让对象的计数器+1(让对象做一次retain操作
(3)尽量不要使用,因为匿名对象会导致内存泄露
(4)谁retain,谁release
(5)谁alloc,谁release
@property的内存管理
1.oc对象类型@proerty (nonatomic ,retain)类名 *属性名
例子 @property(nonatmic,retain)Car *car
@property (nonatomic,retain)id car
2.非oc对象(int \enum\struct)
@property (nonatomic,assign) 类型名称 属性名;
例子 @property(nonatomic,assign) int age
assign:直接赋值,不做任何内存管理(默认,用于非OC对象类型)
自动释放——autorealease
例子 [NSString stringWithFormat ;...];
(1)某个对象收到autorelease消息(方法)时,这个对象加到一个自动释放池中
(2)当自动释放池销毁时,会给池子里面的所有对象发送一条release消息(做一次release操作)
(3)调用autorelease方法时并不会改变对象的计数器,并且会返回对象本身
(4)autorelease实际上只是把对release的调用延迟了,对于每一次autorelease,系统只是把该对象放入了autorelease pool中,当该pool被释放时,该pool中的所有对象会被调用Release
(1)不用再关心对象释放的时间
(2)不用再关心什么时候调用release
(3)占用内存较大的对象不要随便使用autorelease
(4)占用内存较小的对象使用autorelease,没有太大影响
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property (nonatomic, assign) int age;
@end
@implementation Person
- (void)dealloc
{
NSLog(@"Person---dealloc");
[super dealloc];
}
@end
int main()
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
Person *pp = [[[Person alloc] init] autorelease];
[pool release]; // [pool drain];
@autoreleasepool
{
// 1
Person *p = [[[[Person alloc] init] autorelease] autorelease];
// 0
// [p release];
}
return 0;
}
void test()
{
@autoreleasepool
{// { 开始代表创建了释放池
// autorelease方法会返回对象本身
// 调用完autorelease方法后,对象的计数器不变
// autorelease会将对象放到一个自动释放池中
// 当自动释放池被销毁时,会对池子里面的所有对象做一次release操作
Person *p = [[[Person alloc] init] autorelease];
p.age = 10;
@autoreleasepool
{
// 1
Person *p2 = [[[Person alloc] init] autorelease];
p2.age = 10;
}
Person *p3 = [[[Person alloc] init] autorelease];
} // } 结束代表销毁释放池
}
ARC机制
2.指针分2种:
1> 强指针:默认情况下,所有的指针都是强指针 __strong
2> 弱指针:__weak
3.ARC特点
1> 不允许调用release、retain、retainCount
2> 允许重写dealloc,但是不允许调用[super dealloc]
3> @property的参数
* strong :成员变量是强指针(适用于OC对象类型)
* weak :成员变量是弱指针(适用于OC对象类型)
* assign : 适用于非OC对象类型