Object-c基础知识之内存管理(二)

本文深入探讨Objective-C中的内存管理原则,包括引用计数、对象所有权、自动释放池及ARC技术的应用。通过实例讲解dealloc方法的作用及内存管理规则。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Object-c 之内存管理总结

以下仅仅是对内存管理学习的很简单的描述,由于时间问题,自己没有很好的总结整理。写这个很杂的内容 ,日后忘记了这方面的知识,方便可以快速了解这些知识。


主要以下重要几点

 1)、引用计数和对象所有权

 2)、点语法的内存管理

 3)、自动释放池

 4)、ARC和垃圾回收机制

 5)、内存管理常见的错误

 


**

 *引用计数   retainCount : 在整个程序中,对于内存的管理和对象的销毁,就是了解retainCount的变化。 

 *所有者,做了某个动作(创建和保留,赋值),他就拥有了一个对象所有权(ownership

 *alloc  allocWithZone:  copy  copyWithZone:,  mutableCopy  mutableCopyWithZone:   

 *retain 

 *release    autorelease  (不需要某个对象后 ,要释放内存,销毁内存)

 *初始化方法时, 直接向对象发送retain消息,retainCount + 1 ;持有对象所有权。  

 *设置方法中有三点注意:直接赋值,不保留对象;  直接保留对象,在dealloc方法中释放对象;  释放旧对象,保留新对象,在dealloc方法中释放对象

*内存管理规则

Objective-C内存管理准则:

我们可以把上面的接口按对retainCount的操作性质归为两类,
A类是加一操作:1,2,3    (alloc     retain   copy)
B类是减一操作:4,5(延时释放)  (release      autorelease)

内存管理准则如下:
1,A与B类的调用次数保持一制
2,为了很好的保障准则一,以实例对象为单位,谁A了就谁B,没有第二者参与

 **/

/**

 *dealloc方法详解: 当引用计数为0,系统会自动调用dealloc方法,回收内存。 一般都是调用父类的 dealloc 方法

 *子类的某些实例是继承父类的,故,需调用父类的dealloc方法,来释放父类拥有的对象

 *调用顺序,  子类的对象方法释放完,再父类的拥有的对象释放。与初始化相反

 **/

/**

 *赋值  assign :直接赋值,默认    retain 保留对象   copy 拷贝对象

 *读写  readwrite  生成gettersetter 方法 默认     readonly  生成getter

 *原子性  atomic 多线程环境下 ,存在线程保护,默认      nonatomic   不存在线程保护

 *了解以上的各个属性  对应的setter  and  getter methods 

 

 * assign   直接赋值,只是一个别名而已

 * retain     保留这个对象,两个对象指向同一位置

 * copy     开辟了一个新的内存空间,分别指向了不同的内存空间

 **/



/**

 *自动释放池的解析      自动释放池还需要进一步理解

 *1.[pool release] [pool drain] 的区别  前者是要销毁池 ,后者不需要

 *ARC技术,自动管理内存不需要release retain  等等

 *他会自动加入内存的控制代码

 *垃圾回收机制

 **/



代码示例 :


CPU.h     
#import <Foundation/Foundation.h>

@interface CPU : NSObject
{
    @private
    int _cID;
}
//@property int _cID;

-(void) setCID:(int) cID;
-(int) cID;

@end



//cpu.m

#import "CPU.h"

@implementation CPU

//@synthesize _cID;

-(void) setCID:(int) cID{
    _cID = cID ;
}


-(int) cID{
    return _cID;
}

-(void) dealloc{
    NSLog(@"cpu   dead  : %d",_cID);
    [super dealloc];
}
@end


//Laptop.h
#import <Foundation/Foundation.h>

@class CPU;
@interface Laptop : NSObject
{
    @private
    CPU *_cpu;
}

//@property (assign) CPU * _cpu;

-(void) setCPU :(CPU *) cpu;
-(CPU *) cpu;

@end


// Laptop.m

#import "Laptop.h"
#import "CPU.h"

@implementation Laptop

//@synthesize _cpu;


//-(void) setCPU :(CPU *) cpu{
//    _cpu = cpu;
//}  // 第一种情况  普通的赋值


//-(void) setCPU :(CPU *) cpu{
//    _cpu = [cpu retain];  //2
//    NSLog(@"retain :%ld" ,[_cpu retainCount]);
//}  // 第二种情况  保留

-(void) setCPU :(CPU *) cpu{
    if (_cpu != cpu) { //相同对象 不做任何事
        [_cpu release]; //释放了旧对象   当然对 [nil release] 不会产生错误的 如果旧对象为0 了直接会到[cpu dealloc] 中区
        _cpu = [cpu retain];  // 保留新对象
        NSLog(@"retain :%ld" ,[_cpu retainCount]);
    }
    
}  // 第三种情况  保留   优化我们的代码了


-(CPU *) cpu{
    return _cpu;
}

-(void) dealloc{
    
    NSLog(@"laptop dead!!!");
    [_cpu release];  //必须销毁  不然内存泄露
    [super dealloc];
}
@end




   //实例二  所有权的问题  如何持有对象
        // 1.在没有改变CPU之前,情况是如何的:就是 _Cpu 与powePC 指向同一个对象,其中的释放过程要理解清楚
        // 2.在改变了CPU之后,如果没做适当的处理,可能会造成内存泄露,,理解过程就是通过观察retainCount的变化
        // 3._cpu 指向了interCpu
        //
        //4.当旧对象与新对象相同时,可以释放旧对象,保留新对象。当新旧对象相同时,不会做任何事情
        //解决办法: 判断语句
        
        CPU *powerPC = [[CPU alloc] init]; //1
        
        [powerPC setCID:100];
        
        Laptop * apple = [[Laptop alloc] init];
        [apple setCPU:powerPC];
        
        [powerPC release];
        
        CPU *intel = [[CPU alloc] init];
        [intel setCID: 102];
        [apple setCPU:intel];
        [intel release];
        
        [apple release];
        NSLog(@"apple destroy");
         //NSLog(@"laptop cpu id : %d",[[apple cpu] cID]);
        
        
        //dealloc 方法详解
        NSString *carName = [[NSString alloc] initWithFormat:@"audi"];//1
        Car *car =[[Car alloc] initWithName:carName]; //car 1
        [carName release];//0
        
        
        Engine *v6 = [[Engine alloc] init]; //engine 1
        [car setEngine:v6]; //engine 1  但是拥有权交给了Car
        
        [v6 release];  // engine 1  这里释放只是本身对对象的拥有权 ,但是car对象的拥有权
        //do something
        
        [car release];//0
        
        
        
        //点语法的内存管理 。实例  点语法
        
        Propertydemo *proper = [[Propertydemo alloc] init];
        Engine *v7 = [[Engine alloc] init];
        [proper setAge:10];
        [proper setName:@"zhang"];
        [proper setCount:13];
        [proper setEngine:v7];
        
        NSLog(@"age =  %d,  name =  %@ ,   count =  %d ,   engine = %@",[proper age],[proper name],[proper count],[proper engine]);
        
    
        
        

以上代码时看视频学习的 ,要真正的理解内存管理机制 ,就是要看retainCount的变化 ,要理解遵循内存管理规则,,要知道通过什么方法可以获得对象的拥有权。  在程序完了之后要记得释放内存,销毁对象,不然会造成内存泄露。  要真正的理解其中的原理 就是自己写个程序,通过调试,看变化

有Xcode5 以后 引入ARC  所以不需要手动添加内存的释放方法   , 会自动产生管理内存代码的。所以节省了对内存的考虑因素。

 内存管理总结

 1. 当使用了new .alloc copy 方法创建了一个对象时,该对象的引用计数为 1 当不再使用该对象时,要负责向该对象发送release 或者 autorelease 方法 ,这样该对象将在其使用结束时销毁

 2.通过任何其他方法活动对象时,引用计数为 1 而且已经被自动释放,不要执行任何方法来释放该对象, 如果打算在一短时间内拥有该对象,则需要保留它并确保操作完成时释放它。

 3.在程序中 retain  release  方法使用次数必须一致



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值