关闭

Object-C 学习笔记(十)---内存管理MRC

标签: 内存管理
542人阅读 评论(0) 收藏 举报
分类:

内存管理


MRC——手动管理内存

ARC——自动管理内存


MRC

OC采用“引用计数”(retainCount)方式管理对象占用的内存

1.      使用alloc为对象分配内存;使用dealloc释放对象所占用的内存。

2.      使用alloc、new或者copy构造对象是,对象的retainCount为1.

3.      调用对象的retain方法可以增加1 retainCount

4.      调用对象的release方法可以减少1 retainCount

5.      当对象的retainCount为0时,dealloc会自动调用,释放对象内存;否则分配的内存讲被一直占用。

6.      所有对象可以使用retainCount属性查看当前的计数器值。

 

 

例子:

NSString *dadyCar = [[NSStringalloc]initWithFormat:@”Car”];// dadyCar拥有对象所有权retainCount+1

NSString *mumCar = [dadyCar retain];// mumCar拥有对象所有权,retainCount+1

 

NSString *sonCar = [mumCar retain];// sonCar拥有对象所有权,retainCount+1

 

NSString * friendCar = sonCar;// friendCar不拥有对象的所有权,只是简单指向对象内存空间,retainCount不会发生变化

 

[dadyCar release];// retainCount-1

[mumCar release];// retainCount-1

[sonCar release];// retainCount-1

注意:

         如果所有拥有对象的引用都释放了对象的所有权(retainCount=0),那么friendCar就变成了“野指针”,因为对象已经不存在,不能再调用对象的资源。



@property(retain,nonatomic)Strdent

一个类中,如果这个类有属性声明retain或者copy的属性,那么我们需要再这个类的dealloc方法里面释放这个属性。

 

dealloc方法在对象引用计数为0是自动调用。

主要用于适当自身所占用的资源。永远不要手动调用dealloc,应由系统自动调用。

 

真正释放对象内存空间的方位为:dealloc

当一个对象引用计数变成1时,再调用release的时候,其release就会自动调用系统的dealloc方法去释放对象所占的空间。

 

一般在类中需要overwrite覆盖/重写/复写dealloc方法,进行属性控制。

-(void)dealloc//相当于C++的析构方法

{

         //释放子类的引用

         [super dealloc];//调用父类的dealloc,释放父类

}

 

内存释放原则一:

       对象分配内存,并应在使用后,调用release释放内存。

凡是出现retain alloc copy的地方,都应该出现release与之匹配调用。

 

内存释放原则二:

         内存无法确定释放时间是,可以使用autorelease向最近池注册。

         有池决定释放时间

         使用便利构造器获得的对象,都应该是autorelease的。

 

Autorelease://自动释放

——延时释放对象内存。

对于每一个Runloop, 系统会隐式创建一个Autoreleasepool,这样所有的release pool会构成一个象CallStack一样的一个栈式结构,在每一个Runloop结束时,当前栈顶的Autorelease pool会被销毁,这样这个pool里的每个Object会被release。

例子:除了大括号之后,会自动release

 

(1)     当创建的对象未来某个时候销毁是,可以使用对象的autorelease。

(2)     对象讲所有管理权交给最近的NSautoreleasePool对象,并由其全权释放。

 

Autoreleasepool://自动释放池

         对象使用autorelease释放的会放进Autoreleasepool,系统自动释放。


例子:

//
//  People.h
//  Memory
//
//  Created by 5016 on 13-12-4.
//  Copyright (c) 2013年 dradon. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface People : NSObject

//成员属性
@property(retain,nonatomic)NSString* name;
@property(assign,nonatomic)NSInteger age;

-(People *)initWithName:(NSString*) name andAge:(NSInteger) age;

+(People *)PeopleWithName:(NSString*) name andAge:(NSInteger) age;

-(void)toString;


@end

//
//  People.m
//  Memory
//
//  Created by 5016 on 13-12-4.
//  Copyright (c) 2013年 dradon. All rights reserved.
//

#import "People.h"

@implementation People

@synthesize name=_name,age=_age;

-(People *)initWithName:(NSString*) name andAge:(NSInteger) age
{
    if(self = [super init])
    {
        _name = name;
        _age = age;
    }
    return self;
}

//便利构造器
+(People *)PeopleWithName:(NSString*) name andAge:(NSInteger) age
{
    People *person = [[People alloc] initWithName:name andAge:age];
    
    return [person autorelease];//向自动释放池注册
}


-(void)toString
{
    NSLog(@"我的名字是%@,今年%ld岁.",_name,_age);
}

//重写(overwirte)父类方法
-(void)dealloc//用来释放对象的方法,相当于C++里面的析构方法
{
    NSLog(@"这个对象被完全释放");
    self.name = nil;//等价于[_name release]或者[self.name release];
    [super dealloc];
}

@end

//
//  main.m
//  Memory
//
//  Created by 5016 on 13-12-4.
//  Copyright (c) 2013年 dradon. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "People.h"

int main(int argc, const char * argv[])
{
     NSLog(@"|-----------使用alloc开辟对象堆内存空间按-----------------|");
    People *person1 = [[People alloc]initWithName:@"DRAGON" andAge:23];//alloc开辟对象 +1
    [person1 toString];
    NSLog(@"person1的引用计数是:%ld",[person1 retainCount]);
    [person1 retain];//+1 = 2
    NSLog(@"person1的引用计数是:%ld",[person1 retainCount]);
    [person1 release];//-1 = 1 ;这里对象已经释放一次,引用计数为1
     NSLog(@"person1的引用计数是:%ld",[person1 retainCount]);
    [person1 release];//-1 = 0 ;这里对象再释放一次,引用计数为1-1,系统自动调用dealloc
    NSLog(@"person1的引用计数是:%ld",[person1 retainCount]);
    //[person1 release];//再调用一次,则是过度释放,会出现异常
    
    NSLog(@"|-----------使用便利构造器-----------------|");
    @autoreleasepool {//使用自动释放池进行释放,因为程序结束后会释放
        People *person = [People PeopleWithName:@"dragon" andAge:20];
        [person toString];//使用便利构造器 不需要使用release
    }

    return 0;
}

运行结果:



相信到了这里大家会基本理解内存管理.


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场