OC语法基础(6)—手动内存管理

手动内存管理基本概念

与内存管理相关的6个关键字retain release dealloc set @property ,autorelease

内存管理要注意

一个原则:配对原则

两个基本问题://1.野指针操作

//2.内存泄漏

//  Person.h

#import

 

@interface Person : NSObject

 

- (void)run;

 

@end

//  Person.m

#import "Person.h"

 

@implementation Person

 

-(void)dealloc

{

    //在对象自身被销毁之前,一定要先调用[super dealloc]释放父类中的相关对象

    [super dealloc];

    NSLog(@"Person 被销毁了");

}

 

 

- (void)run

{

    NSLog(@"人跑起来了");

}

@end

//  main.m

 

 

#import

#import "Person.h"

 

int main(int argc, const char * argv[])

{

 

    @autoreleasepool {

       

        // 1

        Person * p = [[Person alloc] init];

       

        NSLog(@"%lu",p.retainCount);

       

        // 2

        [p retain];

       

        NSLog(@"%lu",p.retainCount);

       

        // 1

        [p release];

       

        NSLog(@"%lu",p.retainCount);

       

        //0

        [p release];

       

    }

     

   

    return 0;

}

 

单个对象的内存管理分析

//  Person.h

#import

 

@interface Person : NSObject

 

@property int age;

- (void)run;

@end

//  Person.m

#import "Person.h"

 

@implementation Person

 

- (void)dealloc

{

    [super dealloc];

   

    NSLog(@"Person 被销毁了");

}

 

- (NSString *)description

{

    return [NSString stringWithFormat:@"age = %d",_age];

}

- (void)run

{

    NSLog(@"人跑起来了");

}

 

@end

//  main.m

//内存管理原则(配对原则):只要出现了 new,alloc,retain,就一定配对出现一个release,autorelease

//手动内存管理研究问题方法

//1.野指针操作

//2.内存泄漏

 

#import

#import "Person.h"

 

void test()

{

    //retainCount = 1

    Person * p = [[Person alloc] init];

   

    p.age = 10;

    NSLog(@"%@",p);

   

    //retainCount = 0

    //系统已经将p所指向的对象回收了

    //EXC_BAD_ACCESS 访问了不可访问的内存空间

    //被系统回收的对象我们称之为僵尸对象

    //默认情况下xcode为了提高编码效率,不会时时检查僵尸对象

   

    [p release];

   

    //        NSLog(@"p所指向的对象回收了 %@",p);

    //        p.age = 20;//[p setAge:20];

    [p run];

 

}

 

void test2()

{

    Person * p = [[Person alloc] init];

    p.age = 20;

   

    NSLog(@"%@",p);

   

    [p release];

    //如果你确定当前作用于中的对象已经不会再被使用了,为了防止野指针操作,通常我们会把不在使用的指针变量赋值为nil

    p = nil;

   

    p.age = 30;//[nil setAge:30];

    [p run]; //[nil run];

    //避免野指针操作的方法 [nil resele]

 

}

void test3()

{

   

   

   

   

    //1

    Person * p = [[Person alloc] init];

   

    p.age = 20;

    [p run];

   

    Person * p1 = p; // 此处并不会使对象的应用计数加一

   

    //0

    //        [p release];

    [p1 release];

   

    //野指针操作

    p1.age = 20;

 

}

void test4()

{

    //1

    Person * p = [[Person alloc] init];

   

    p.age = 20;

    NSLog(@"%@",p);

   

    //0

    [p release];

   

    //野指针操作,当一个对象retainCount已经为0 ,调用retain方法,是不会使得对象起死回生的,同时还会发生野指针操作异常

    [p retain];

}

 

void test5(Person * p)

{

    p.age = 30;// release retain

    [p retain]; //2

//    [p release];

    NSLog(@"%@",p);

}

 

int main(int argc, const char * argv[])

{

 

    @autoreleasepool {

       

        //1

        Person * p = [[Person alloc] init];

        p.age = 20;

       

//        test5(p);

        //1

        [p release];

        //0

        [p release];

  

    }

    return 0;

}

 

多个对象的内存管理分析(写法上不完美仅做例子)

//  Car.h

#import

 

@interface Car : NSObject

 

- (void)run;

 

@end

//  Car.m

#import "Car.h"

 

@implementation Car

 

- (void)dealloc

{

    [super dealloc];

    NSLog(@"Car 被销毁了");

}

 

- (void)run

{

    NSLog(@"汽车跑起来了");

}

 

@end

//  Person.h

#import

#import "Car.h"

 

@interface Person : NSObject

{

    Car * _car;

}

 

- (void)setCar:(Car *)car;

- (Car *)car;

 

- (void)drive;

 

@end

//  Person.m

#import "Person.h"

 

@implementation Person

 

- (void)setCar:(Car *)car

{

    //2,能够使得retainCount + 1 并且返回self

    _car  = [car retain];

 

}

- (Car *)car

{

    return _car;

}

 

- (void)drive

{

    [_car run];

}

- (void)dealloc

{

    //目的是要保证在p对象存在的时候,car对象一定存在

    //对象p被销毁的时候,

    [_car release]

    [super dealloc];

    NSLog(@"Person 被销毁了");

}

 

@end

//  main.m

#import

 

//人拥有一辆汽车

#import "Person.h"

 

 

//1.野指针问题

//2.内存泄漏问题

int main(int argc, const char * argv[])

{

 

    @autoreleasepool {

       

        // 1

        Person * p = [[Person alloc] init];

       

        // 1

        Car * car = [[Car alloc] init];

   

        //2

        [p setCar:car];

       

        [p drive];

    

      

        //1

        [car release];

       

        //要保证对象p 存在的时候,调用对象p的任何方法都不会出错

        [p drive];

       

        //0

        [p release];

       

    }

    return 0;

}

set方法的内存管理分析(重点、难点)

//  Car.h

#import

 

@interface Car : NSObject

 

@property int speed;

 

- (void)run;

 

@end

//  Car.m

#import "Car.h"

 

@implementation Car

 

- (void)dealloc

{

    [super dealloc];

    NSLog(@"Car 被销毁了 %d速度",_speed);

}

 

- (void)run

{

    NSLog(@"汽车跑起来了");

}

 

@end

//  Person.h

#import

#import "Car.h"

 

@interface Person : NSObject

{

    Car * _car;

    NSString * _name;

}

 

- (void)setName:(NSString *)name;

- (NSString *)name;

 

- (void)setCar:(Car *)car;

- (Car *)car;

 

- (void)drive;

 

@end

//  Person.m

#import "Person.h"

 

//配对原则:new alloc retain 对应一个release,autorelease

 

@implementation Person

 

- (void)setName:(NSString *)name

{

    if (_name != name)

    {

        [_name release];

        _name = [name retain];

    }

   

}

- (NSString *)name

{

    return _name;

}

//面试笔试,出题率非常高

- (void)setCar:(Car *)car

{

 

    if (_car != car)

    {   //c1 0

        //relese旧值

        [_car release];//[nil release];

        //c2 2

        //retain新值

        _car  = [car retain];

    }

 

}

- (Car *)car

{

    return _car;

}

 

- (void)drive

{

    [_car run];

}

- (void)dealloc

{

    //目的是要保证在p对象存在的时候,car对象一定存在

    //对象p被销毁的时候,

    //0

    //c2 0

    [_car release];

    [_name release];

    [super dealloc];

    NSLog(@"Person 被销毁了");

}

 

@end

//  main.m

#import

#import "Person.h"

 

int main(int argc, const char * argv[])

{

 

    @autoreleasepool {

       

         //p  1

        Person * p = [[Person alloc] init];

       

      // c1 1

        Car * c1 = [[Car alloc] init];

        c1.speed = 100;

       

       //c1 2

        [p setCar:c1];

       

        [p drive];

       

         //c1 1

        [c1 release];

       

       

       

       

       

       //c2 1

        Car * c2 = [[Car alloc] init];

        c2.speed = 350;

       

        //c2  2

        [p setCar:c2];

       

       

        [p drive];

       

        //c2 1

        [c2 release];

       

 

        //p 0

        [p release];

       

    }

    return 0;

}

@property参数

//  Person.h

#import

#import "Car.h"

@interface Person : NSObject

 

//1.生产getset方法的声明

//2.生成getset方法的简单实现

//3.若果你没有声成名相对象的成员变量,那么他会自动生成一个_开头的成员变量

 

//@property 参数分为4

 

 

//2.多线程相关

//nonatomic: 不生成多线程线管代码,使用这个就可以了(效率高一点)

//atomic:生成多线程线管代码(不写默认是这种方式)

//实际开发中,只要是对象类型的@property都写成下面

@property (nonatomic,retain) Car * car;

 

//3.是否要生成setget方法

//readwrite: 可读可写属性,同时生成setget方法

//readonly : 只读属性,只生成get方法

 

//4.setget方法名称相关的参数

//setter:设置生成的set方法名称

//getter:设置生成的get方法名称

 

@property (nonatomic,retain) Car * car;

@property (nonatomic,retain)NSString * name;

@property (nonatomic,assign)int age; //int float double char

@property (nonatomic,assign)int weight;

@property (nonatomic,assign,readonly)int idCard;

@property (nonatomic,assign,setter = abc:,getter = zhuanghuimei)int height;

//改变setget方法名称很多都是用在BOOL类型的变量

@property (nonatomic,assign,setter = isDeid:,getter = isDeid)BOOL isDeid;

 

//- (void)isDeid:(BOOL)isDeid;

 

//- (void)setHeight:(int)height;

//- (int)height;

 

 

@end

//  Person.m

#import "Person.h"

 

@implementation Person

 

- (void)dealloc

{

    //如果一个对象被生成成了成员变量或者是使用@property生成的符合内存管理的set方法,那么一定要在 dealloc函数对应一次release操作

    [super dealloc];

    [_car release];

    NSLog(@"Person 被销毁了");

}

 

@end

//  Car.h

#import

 

@interface Car : NSObject

 

@end

//  Car.m

 

#import "Car.h"

 

@implementation Car

 

-(void)dealloc

{

    [super dealloc];

    NSLog(@"Car 被销毁了");

}

 

@end

//  main.m

#import

#import "Person.h"

 

int main(int argc, const char * argv[])

{

 

    @autoreleasepool {

       

        Person * p = [[Person alloc] init];

       

        Car * car = [[Car alloc] init];

       

        //car 2

        [p setCar:car];

       

        //car 1

        [car release];

       

 

       

        [p abc:100];

        int b = [p zhuanghuimei];

        p.height = 100;//[p abc:10];

        NSLog(@"he %d",p.height);//[p zhuanghuimei];

        //p 0      

       

        [p isDeid:YES];

        [p isDeid];

        p.isDeid = YES;

        BOOL result  = p.isDeid;

               

        [p release];

           

    }

    return 0;

}

autorelease基本概念

//  Person.h

#import

 

@interface Person : NSObject

 

@end

//  Person.m

#import "Person.h"

 

@implementation Person

 

- (void)dealloc

{

    [super dealloc];

    NSLog(@"Person 被销毁了");

}

 

@end

//  main.m

//内存管理原则(配对原则):只要出现了new,alloc,retain方法,就要配对出现release,autorelease

//对象存入到自动释放池中,当这个池子被销毁的时候他会对池子中所有的对象进行一次release操作

//怎么把对象存到池子中

#import

#import "Person.h"

 

int main(int argc, const char * argv[])

{

   

   

   

    // 示例3

   

    //示例4

   

   

    //示例5

   

   

   

    Person * p = [[Person alloc] init];

   

    @autoreleasepool {

       

        [p autorelease];

       

        @autoreleasepool {

           

        

            [p autorelease];

        }//[p release] 0

       

       

    }//[p release];

   

   

    return 0;

}

 

 

autorelease应用(最重要的应用)

//  Food.h

#import

 

@interface Food : NSObject

 

@property(nonatomic,retain) NSString * name;

 

@end

//  Food.m

#import "Food.h"

 

@implementation Food

- (void)dealloc

{

    [super dealloc];

    [_name release];

    NSLog(@"Food被销毁了");

}

 

@end

//  Chief.h

 

#import

#import "Food.h"

 

@interface Chief : NSObject

 

+ (Chief *)chief;

- (Food *)chiefMakeFood;

 

@end

//  Chief.m

#import "Chief.h"

 

@implementation Chief

 

- (void)dealloc

{

    [super dealloc];

    NSLog(@"厨师被回收了");

}

 

+ (Chief *)chief

{

   

   

    Chief * chi = [[self alloc] init];

   

   

    return [chi autorelease];

}

- (Food *)chiefMakeFood

{

  

 

    //如果在方法中创建一个对象,最好给我初始化为nil,防止出现野指针错误

    // 1

    Food * food = [[Food alloc] init];

    food.name = @"凑豆乳";

//    // 0

//    [food release];

    [food autorelease];

   

    return food;

   

}

 

@end

//  main.m

#import

#import "Chief.h"

//autorelease笔试面试出现的几率比[release]

 

int main(int argc, const char * argv[])

{

 

    @autoreleasepool {

   

       

       

 

       

        Chief * chi = [Chief chief];

        Food * food = [chi chiefMakeFood];

        // 这是autorelease应用的最重要的两点:在类方法和对象方法中创建了对象,这种类型的对象不能直接release

              // 而是用autorelease ,这里体现了谁创建誰释放<</span>这里通过方法间接创建,可以理解成由系统创建,当然

              // 由系统的autorelease释放>

        NSLog(@"%@",food.name);

       

        NSString * name = [NSString stringWithFormat:@"%@",@"施瓦辛格"];//都是autorelease

 

        NSLog(@"%@",name);

       

    }

    return 0;

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值