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

本文介绍了Objective-C中的内存管理原理及实践,包括为何需要内存管理、内存管理的基本原理、关闭ARC功能的方法、内存管理的原则,以及如何处理多个对象之间的内存管理。


一、为什么要内存管理

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

 

二、内存管理的原理

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

 

三、关闭ARC

ARCAutom 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

bookh

#import <Foundation/Foundation.h>
 
@interface<a target=_blank class="izllvbhl" href="#" title="Click to Continue > by MacVx"> book<img src="https://i-blog.csdnimg.cn/blog_migrate/967e5b9afc9c7c88a4dc8436fa94f9ac.png" alt="" /></a> : NSObject
{
    int _price;
}
- (void)setPrice:(int)price;
- (int)price;
 
@end


bookm

#import <a target=_blank class="izllvbhl" href="#" title="Click to Continue > by MacVx"> book<img src="https://i-blog.csdnimg.cn/blog_migrate/967e5b9afc9c7c88a4dc8436fa94f9ac.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="https://i-blog.csdnimg.cn/blog_migrate/967e5b9afc9c7c88a4dc8436fa94f9ac.png" alt="" /></a>.h"
 
@interface Person : NSObject
{
   <a target=_blank class="izllvbhl" href="#" title="Click to Continue > by MacVx"> book<img src="https://i-blog.csdnimg.cn/blog_migrate/967e5b9afc9c7c88a4dc8436fa94f9ac.png" alt="" /></a> *<a target=_blank class="izllvbhl" href="#" title="Click to Continue > by MacVx"> book<img src="https://i-blog.csdnimg.cn/blog_migrate/967e5b9afc9c7c88a4dc8436fa94f9ac.png" alt="" /></a>;
}
- (void)setBook:<a target=_blank class="izllvbhl" href="#" title="Click to Continue > by MacVx"> book<img src="https://i-blog.csdnimg.cn/blog_migrate/967e5b9afc9c7c88a4dc8436fa94f9ac.png" alt="" /></a> *<a target=_blank class="izllvbhl" href="#" title="Click to Continue > by MacVx"> book<img src="https://i-blog.csdnimg.cn/blog_migrate/967e5b9afc9c7c88a4dc8436fa94f9ac.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对象就被销毁了,但是pBook对象还有一个引用,这样是不合理的!

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

运行程序

 

只有Person对象被回收了!

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

 

 

 

 

 


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值