阅读更多
由于内存管理部分较难理解,所以记录在此以备不时之需,如有错误和不足欢迎大家指正。
手动内存管理(MRC)部分:
1.引用计数:生成一个对象的时候,将对象的引用计数记为1,每调用该对象一次引用计数就加一,不使用时便减一,只到引用计数为0并释放。
2.当对象使用[p retain],[p alloc],[p new],copy,Mutablecopy方法时,均可以使retainCount加一。
当对象使用[p release]时,引用计数减一,[p retainCount]可以查看引用计数。
3.内存管理错误的几种类型:
1.内存泄漏:对象在不使用时未释放
2.野指针:对象提前释放
3.僵尸对象:执行过度释放方法
4.dealloc方法的使用:- (void)dealloc {self.dog = nil; [super dealloc];}
该方法为引用计数为0时系统自动调用,不能手动调用 (具体实例下面会给出)
5.关于对象所有权的问题:
1.定义:如果一个对象内有指向其他对象的实例变量,则称该对象拥有这些对象。
2.内存管理法则:谁申请,谁释放。
3.正因为在多个实体中对象所有权关系复杂,所以要保留引用计数大于一。
举例:在Car类中有- (void)setWheel:(Wheel *)newWheel;
在main函数中调用该方法:Wheel * wheel = [[Wheel alloc] init];
[car setWheel:wheel];
现在就出现了问题:如果wheel对象属于main函数,但Car类正在使用它,
可如果属于Car类,又不敢保证之后main函数不会再使用这个对象。
解决方法如下:让Car类保留wheel对象,并使引用计数器的值为2,
这是因为main函数和Car类都在使用wheel这个对象,Car类应该
在setWheel方法保留这个对象,main函数负责释放这一对象,当
Car类完成其功能时再通过系统调用dealloc方法进行释放该对象。
6.访问set方法中的保留与释放写法:
1.如果我在set方法里写 wheel = [newWheel retain];则在main函数中
以 Wheel *wheel1 = [Wheel new]; [car setWheel:wheel1];
[wheel1 release]; 会出现内存泄漏的错误,因为此时wheel的引用
计数仍然为1,main函数释放了wheel1而Car类并未释放。
2.如果我在set方法里写 [wheel release]; wheel = [newWheel retain];
则在main函数中以 Wheel *wheel = [Wheel new]; Car *car1 =
[Car new]; Car *car2 = [Car new]; [car1 setWheel: wheel];
[wheel release]; [car2 setWheel: [car1 wheel]]; 由于newWheel
和wheel均指向刚释放的内存区,以至会引发错误。
3.正确的写法之一:在set方法里写:[newWheel retain]; [wheel release];
wheel = newWheel; 这样写的原因是首先保留新的wheel对象,就算两者是
同一对象引用计数也会先加一,然后立即释放掉,再把newWheel赋给wheel,
在set方法中先保留新对象,再释放对象就不会出现错误。