1.alloc是创建变量,dealloc是释放变量,retain是计数加1,release是计数减1
如果使用名字以alloc
或new
开头或名字中包含copy
的方法(如alloc、newObject或mutableCopy)创建一个对象,则会获得该对象的所有权;或者如果向一个对象发送了一条retain
消息,则也会获得该对象的所有权.可以使用释放release
或自动释放autorelease
来释放一个对象的所有权.自动释放autorelease
的意思是"将会发送释放release
消息".
Objective-C中没有new
和delete
这两个关键字(new
可以看作是一个函数,也就是alloc
+init
).他们实际被alloc
和releas
取代.
alloc
与dealloc
语意相反,alloc
是创建变量,dealloc
是释放变量.retain
对应releas
,其保留一个对象,调用之后变量的计数+1.仅这样或许不是很明显,下面就一起看个例子:
-(void)setName:(NSString *)name {
[name retain];
[myName release];
myName = name;
}
下面来解释一下.设想,用户在调用这个函数的时候注意了内存的管理,所以小心的写下了如下的代码:
NSSting*newName = [[NSSting alloc]initWithString:@"Jone"];
[aClass setName:newName];
[newName release];
来看一下newName
的计数是怎么变化的.首先,他被想alloc
,count= 1
;然后,在setName
中.它背retain
,count = 2
;最后,用户自己释放newName
,count = 1
,myName
指向了�newName
.这也解释了为什么需要调用[myName release].需要在给myName赋新值的时候,释放掉以前旧的变量.retain
之后直接dealloc
对象计数器没有释放.alloc
需要release
配对使用,因为alloc
这个函数调用之后变量调用之后,变量的计数+1.所以调用alloc之后,一定要调用对应得release
.另外,在release
一个变量之后,它的值仍然有效,所以在调用alloc
之后,一定要调用对应的release
.另外,在release
一个变量之后,它的值仍然有效,所以最好是后面紧接着在var = nil
.
2.分配过程(alloc和init...)不仅进行对象的内存分配,还要对它的isa 实例变量和保持数据初始化
当分配一个对象时,Cocoa
进行的部分工作可以由"分配"这个术语看出来.Cocoa
会从应用程序的虚存区中为对象的实例变量,包括它们的类型和顺序,这些信息由对象的类来定义.为了进行对象分配,需要向对象的类发送alloc
或allocWithZone:
消息.在消息的返回值中可以得到一个"生的"(未初始化�的)类实例.alloc
方法使用应用程序默认的虚存区.区是一个按页对齐的内存区域,用于存放应用程序分配的对象和数据.
除了分配内存之外,Cocoa的分配(allcoation)消息还进行其他一些重要的工作:
1,将对象的保持数设置为1(如"Cocoa
对象的生命周期"部分所述).
2,使初始化对象的isa实例变量指向对象的类.对象类是一个根据类定义编译得到的运动时对象
3,将其他所有的实例变量初始化为0(或者与0等价的类型,如nil
,NULL
和0.0).
对象的isa
实例变量是从NSObject继承下来的,因此所有的Cocoa对象都有.(类和实例)网络中了.其结果是对象可以找到它所需要的所有运行时信息,比如其他对象在继承层次上的位置、他们遵循的协议,以及在响应消息时可以执行的方法实现的位置.
总之,分配过程不仅进行对象的内存分配,而且还初始化对象的两个而且非常重要的属性,即它的isa
实例变量和保持数.它还将所有剩下的实例变量设置为0.但是分配完成的对象还是不可用,还需要调用像init
这样的初始化方法来进行对象自有的初始化,才能返回一个可用的对象.
对象赋值时尽量采用autorelease而不是retian模式
当创建新的临时对象时,在同一行代码里就设定autorelease
,而不是写到这个方法的后面几行去.虽然这样可能会造成一些轻微的延迟,但这样避免了谁不小心把release
去掉,或在release
之前就return
而造成的内存泄漏,如下所示:
//AVOID (unless you have a compelling PerforMance reason)
MyController *controller =[[MyController alloc]init];
//...code here that might return...
[controller release];
//BETTER
MyController *controller = [[[MyController alloc]init]autorelease];
对象赋值时尽量采用autorelease
而不是retian
模式.当把一个创新的对象赋予一个变量的时候,第一件事要做的事情就是先释放原来的变量指向的对象以防止内存泄漏.这里也有很多"正确的"方法去做这件事.选择autorelease
是因为它更不倾向于出错.小心在密集的循环里可能会很快填满autorelease
池,而且它也确实会减低了效率但权衡下来还是可以接受的.
- (void)setFoo:(CMFoo *)aFoo{
[foo_autorelease];// Wo't dealloc if|foo_|==|aFoo|
foo_ = [aFoo retain];
}
使用autorelease
来发送一个延迟release
.典型的使用场景:函数返回一个对象的时候.例如,可以像这样的实现fullName的方法:
-(NSString *)fullName = {
NSSting *sting = [[[NSSting alloc]initWithFormat:@"%@,%@", self.firstName, self.lastName]autorelease];
return sting;
}
上面就是典型的场景:想放弃对象的所有权,但是又想让调用在sting销毁前使用返回值.
还可以通过下面的实现达到上面的效果:
-(NSSting)fullName {
NSSting *sting = [NSString stingWithFormat:@"%@,%@", self.firstName, self.lastName];
return sting;
}
要点
(1)alloc
是创建变量,dealloc是释放变量,retain
是计数+1,release
是-1.
(2)分配过程(alloc 和 init...)不仅进行对象的内存分配,还有对它的isa实例变量和保持数初始化.
(3)对象赋值时尽量采用autorelease
而不是retain
模式.