内存管理备忘:
这是在main方法中调用:
上面这段程序出错原因:
[car1 Engine]返回一个指向engine对象的指针,该对象的保留计数器值为1.setEngine方法的第一行是[Engine release],该语句将engine对象的保留计数器值归0,并释放engine对象。现在newEnging和engine这两个实例变量都指向刚释放的内存区,引起错误。
如果首先保留新的engine对象,而newEngine与engine是同有一个对象,保留计数器值将先增加,然后立即减少,但不会归0,Engine对象意外地未被销毁,从而导致错误。在访问方法中,如果先保留新对象,然后再释放旧对象,则不会出问题。
每个对象有一个与之相关联的整数,称作它的引用计数器或保留计数器。当某段代码需要访问一个对象时,该代码将该对象的保留计数器值加1,表示“我要访问该对象”。当这段代码结束对象访问时,将对象的保留计数器减1,表示塔不在访问对象。当保留计数器值为0时,表示不再有代码访问该对象了,因此该对象占用的内存被系统回收。
当使用alloc、new、或copy消息(生成接收对象一个副本)创建一个对象时,对象的保留计数器值加1。
retain 增加对象的保留计数器值。
release 减少对象的保留计数器值
使用实例:
访问方法中的保留和释放:
错误实例:
假设这是在car类中:
-(viod) setEngine:(Engime *) newEngine
{
[engine release];
engine=[newEngine retain];
}
这是在main方法中调用:
Engine *engine=[Engine new];//count: 1 这里实例化了Engine方法而使保留计数器值加1(原先为0)
car *car1=[Car new]; //实例类
car *car2=[Car new];//实例类
[car1 setEngine:engine];//count:2 把engine当成一个对象传给 car1中的setEngine ,因为endine对象本身有一个保留计数器1 通过engine=[newEngine retain]; 后 变成2
[engine release];//count 1释放engine保留计数器
[car2 setEngine:[car1 engine]];//oops!
上面这段程序出错原因:
[car1 Engine]返回一个指向engine对象的指针,该对象的保留计数器值为1.setEngine方法的第一行是[Engine release],该语句将engine对象的保留计数器值归0,并释放engine对象。现在newEnging和engine这两个实例变量都指向刚释放的内存区,引起错误。
下面是编写setEngine的一种更好方法:
-(void) setEngine:(Engine *)newEngine
{
[newEngine retain];
[engine erlease];
engine=newEngine;
}
如果首先保留新的engine对象,而newEngine与engine是同有一个对象,保留计数器值将先增加,然后立即减少,但不会归0,Engine对象意外地未被销毁,从而导致错误。在访问方法中,如果先保留新对象,然后再释放旧对象,则不会出问题。
垃圾回收:只需转到项目信息窗口的Build选项卡,然后选择Required[-fobjc-gc-only]选项即可.
(“-fobjc-gc” 选项时为了使代码即支持垃圾回收又支持对象的保留和释放,例如两种环境都适用的库代码)
启用垃圾回收以后,通常的内存管理命令全部变成了控操作指令,不执行任何操作.