iOS基础之Objective-C(五)

内存管理

1、内存管理范围:
需要new或者需要alloc、init等关键字创建的对象类型,对于float,char,double,struct,enum等基本数据类型不需要我们去管理他们的内存。(解释:因为对象类型会放在堆中,而非对象类型会存放在栈中,栈中的数据会被系统自动回收)


2、堆与栈
堆:一般由程序员分配与释放,如程序员不释放,当程序结束时,可能由系统回收,分配方式类似于链表;
栈:由操作系统自动分配与释放,一般用于存放形参,局部变量等值。
例:

int main() {
  Person *p = [[Person alloc] init];
}

其中:p存放在栈中,而Person存放在堆中


3、引用计数器
(1)、每一个oc对象都有一个自己的引用计数器
(2)、他是一个整数,占4个字节
(3)、含义:对象被引用的次数或者有多少东西正在用这个对象
(4)、引用计数器为0时,对象占用的内存会被系统回收;大于0时,对象的内存不会被回收,除非程序退出了;任何一个对象,被创建以后,引用计数器为1(如使用new,alloc,copy等创建的对象)。
(5)、引用计数器常见操作:
a、retain:引用计数器+1
b、release:引用计数器-1(仅代表计数器-1,不代表销毁对象
c、retainCount:获取当前计数器的值


4、dealloc方法
(1)、当对象的引用计数器为0,对象即将被销毁时,系统会给对象自动调用delloc方法,通过判断有没有调用dealloc方法就可以判定对象有没有被销毁;
(2)、dealloc的重写:
一般在重写的dealloc方法中释放资源,且需要调用[super dealloc],并且是放在重写的dealloc方法中的最后;
(3)、一般不能直接调用dealloc方法,因为调用了就会释放对象占用的内存,操作不当,会造成野指针。


5、僵尸对象与野指针
僵尸对象:如果一个对象已经被释放了,那么称这个对象为僵尸对象
野指针:指向已被释放的对象(即僵尸对象)的指针,我们称之为野指针。


6、空指针
没有指向存储空间的指针(里面存放的是nil,也就是0)
给空指针发送消息没有反应,但是程序不会报错也不会崩溃
未避免野指针,在对象被销毁之后,将对象指向的指针变为空指针(在MRC中)

7、内存管理说明以及retain和assign关键字:
当A对象想使用B对象时一定要对B对象进行一次retain,这样才能保证A对象存在B对象也存在,换句话说就是,无论什么时候,A对象都可以使用B对象,当A对象release时,一定要对B对象也进行一个release。

@interface A:NSObject {
  B *_b;
}
@end
  
@implementation

-(void)setB:(B *)b{
  [b retain];
  _b = b;
}

-(void)delloc {
  [_b release];
  [super delloc];
}
@end

为避免发生僵尸对象与野指针的情况,set方法最好改写成以下形式:

-(void)setB:(B *)b{
  if(b != _b) {
    [_b release];  //原数据释放
    _b = [b retain];  //新数据保存;  retain不但会将引用计数+1还会返回对象本身
  }
}

但是如果每个属性都要这么写一遍,将会非常繁琐,所以我们在声明属性的时候可以声明成这样:

@property (retain) B *b;

此时我们可以不用自己去实现setter和getter方法,他会自动将属性实现成类似上面的方法。
而asign不具备管理对象的能力,只能适用于基本数据类型,所以他说实现的将会没有release和retain的getter和setter方法,如下所示:

@property (retain) NSInteger *num;
//实现的setter方法如下所示
-(void)setNum:(NSInteger)num {
  _num = num;
}

总结:assign不会帮我们生成具备内存管理的setter和getter方法,只会生成默认的方法,如果在@property后面什么都不写,则会将其视为assign;而retain会帮我们生成具备内存管理的setter和getter方法。

8、atomic与nonatomic:
atomic:线程安全,但是性能很低
nonatomic:线程不安全,但是性能相对会高很多

9、MRC与ARC
MRC(手动管理内存):在MRC的内存管理模式下,与对变量的管理相关的方法有:retain,release和autorelease。retain和release方法操作的是引用记数,当引用记数为零时,便自动释放内存。并且可以用NSAutoreleasePool对象,对加入自动释放池(autorelease调用)的变量进行管理,当drain时回收内存。
和内存管理相关的方法
1)alloc 引用计数器自动设为1
2)retain 引用计数器+1 返回了经过+1以后的当前实例对象
3)release 引用计数器-1,并不一定是释放
4)retainCount 获取引用计数器的值
5)dealloc 当实例对象被销毁之前,系统自动调用。
一定要调[super dealloc]
6)autorelease,该方法是将该对象内存的管理放到autoreleasepool中。

ARC(自动管理内存,Xcode 4.1/iOS5以后的特性),需要注意的是他是编译器特性,编译器帮助我们插入那些内存管理方法,同时他和其他语言的垃圾回收机制也有很大的不同

对比:
ARC中强引用的strong,相当于MRC中的retain
ARC中弱引用的weak,相当于MRC中的assign
ARC中保存基本数据类型的assign,跟MRC中的assign一样

PS:在ARC中,保存弱引用不要用assign,assign是用来保存基本数据类型的,如果要保存弱引用,需要使用weak

你可能感兴趣的:(iOS基础之Objective-C(五))