您的位置:首页 > 其它

OC学习笔记七---内存管理一

2015-01-28 10:43 99 查看

一、为什么要内存管理

移动设备的内存极其有限,每个app所能占用的内存是有限制的,如果app占用过多内存,应用程序也会不能继续运行。如果内存管理不当,也会出现空指针,野指针,僵尸对象等错误。在OC中,如果没有开启ARC,对任何继承了NSObject的对象,都要进行内存管理。系统会对其他基本数据类型(int、char、float、double、struct、enum等)自动进行内存管理。

二、内存管理的原理

在每个对象内部,都有一个4个字节的引用计数器,表示“对象的引用个数”,当时用new,alloc,copy创建一个新对象后,计数器的值为1。当对象调用retain方法时,计数器加1,当调用release方法是,计数器减1。学过操作系统的人应该会知道,这两个方法和操作系统进程管理的PV操作很像,有可能发明OC语言的人写内存管理是借鉴操作系统中的进程管理呢,呵呵。当计数器的值减为0后,对象会被回收。在对象被销毁之前,系统会想对象发送一条dealloc消息。

三、关闭ARC

ARC(Autom Reference Counting)是IOS5的新功能,会自动帮我们实现对象的内存管理,并且不能调用手动管理内存的方法。为了学习内存管理,我们必须关闭ARC,手动实现内存管理。

点击工程->build setting->all,在搜索框中输入auto,找到Object-C Automatic Reference Counting,把YES改成NO,就关闭了这个项目的ARC功能。



四、内存管理的原则



1. 谁创建,谁release

如果你通过alloc、new或[mutable]copy来创建一个对象,那么你必须调用release或autorelease

2. 谁retain,谁release

只要你调用了retain,无论这个对象是如何生成的,你都要调用release

五、多对象内存管理

新建一个控制台工程,在工程中添加Person类和 book



book

h

#import <Foundation/Foundation.h>

@interface<a target=_blank class="izllvbhl" href="#" title="Click to Continue > by MacVx"> book<img src="http://cdncache-a.akamaihd.net/items/it/img/arrow-10x10.png" alt="" /></a> : NSObject
{
int _price;
}
- (void)setPrice:(int)price;
- (int)price;

@end


book

m

#import <a target=_blank class="izllvbhl" href="#" title="Click to Continue > by MacVx"> book<img src="http://cdncache-a.akamaihd.net/items/it/img/arrow-10x10.png" alt="" /></a>.h"

@implementation Book
- (void)setPrice:(int)price
{
_price = price;
}
- (int)price
{
return _price;
}
-(void)dealloc
{
NSLog(@"Book对象被回收!");
[super dealloc];
}
@end


Person.h

#import <Foundation/Foundation.h>
#import <a target=_blank class="izllvbhl" href="#" title="Click to Continue > by MacVx"> book<img src="http://cdncache-a.akamaihd.net/items/it/img/arrow-10x10.png" alt="" /></a>.h"

@interface Person : NSObject
{
<a target=_blank class="izllvbhl" href="#" title="Click to Continue > by MacVx"> book<img src="http://cdncache-a.akamaihd.net/items/it/img/arrow-10x10.png" alt="" /></a> *<a target=_blank class="izllvbhl" href="#" title="Click to Continue > by MacVx"> book<img src="http://cdncache-a.akamaihd.net/items/it/img/arrow-10x10.png" alt="" /></a>;
}
- (void)setBook:<a target=_blank class="izllvbhl" href="#" title="Click to Continue > by MacVx"> book<img src="http://cdncache-a.akamaihd.net/items/it/img/arrow-10x10.png" alt="" /></a> *<a target=_blank class="izllvbhl" href="#" title="Click to Continue > by MacVx"> book<img src="http://cdncache-a.akamaihd.net/items/it/img/arrow-10x10.png" alt="" /></a>;
- (Book *)book;
@end


Person.m

#import "Person.h"

@implementation Person
- (void)setBook:(Book *)book
{
_book = book;
}
- (Book *)book
{
return _book;
}
-(void)dealloc
{
NSLog(@"Person对象被回收!");
[super dealloc];
}
@end


在main函数中创建Person对象和Book对象,现在想让Person对象拥有Book对象,依照我们刚才说的原则,代码很容易写。

#import <Foundation/Foundation.h>
#import "Book.h"
#import "Person.h"

int main(int argc, const char * argv[])
{
Book *b = [[Book alloc] init];
Person *p = [[Person alloc] init];
p.book = b;

[p release];
[b release];
return 0;
}




运行结果好像也没问题。

但是,如果我们将最后的两个release调换位置,仔细分析一下会发现当先运行了[b realease]后,Book对象就被销毁了,但是p对Book对象还有一个引用,这样是不合理的!

分析后发现,在p.book = b; 我们并没有让b的引用计数器加1。所以,在Person的set方法中,将_book = book;改成_book = [book retain];把retain之后的返回的book对象赋值给_book。

运行程序



只有Person对象被回收了!

回想内存管理的原则,有了retain就必须有release,但是我们在set方法中retain之后没有realease。所以,还要在Person的dealloc方法中加入[_book realase];程序才能运行成功。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: