• OC-手动引用计数内存管理


    什么是引用计数内存管理

    通过使用 引用计数 跟踪每个对象被引用的次数 当对象引用次数为0时系统就会释放这个对象占用的内存

    过程

    实例B是类A的实例对象
    如果有地方要用到实例B,则类A会给实例B发送一个retain消息,每执行一次retain就使引用计数+1 如果不再需要这个对象了 则发生release是对象的引用计数-1
    但是运行时没有愈发标记或者对象中的属性会记录当前这个对象具体是被哪个对象所有

    retain计数+1

    alloc 、new 或者copy创建一个对象时,新对象的引用计数器默认就是1
    一般函数里面要用到这个对象就retain 赋值也需要

    release计数-1

    release只是单纯的将引用计数-1 释放内存的并不是release 而是dealloc(alloc是类方法,dealloc是实例方法)
    当对象的引用计数值为0时 Objective-C会自动向对象发送一条dealloc消息来释放内存。
    所以在写“析构函数”的时候要重写的是dealloc函数 而不是release函数
    这个函数结束了就release

    问题:是不是一个对象引用计数时1的时候release他 是不是还能用 他就归零了

    自动释放机制

    将所有需要发送release消息的对象都记录到NSAutoreleasePool(自动释放池) 最后一起release
    当想一个对象发送autorelease消息就会把这个对象加入到NSAutoreleasePool中,当NSAutoreleasePool被销毁时会将记录下来的的所有对象release

    id pool = [[NSAUtoreleasePool alloc]init];
    /*
    给临时对象发送autorelease消息
    */
    [pool release];//销毁自动释放池 将池里的所有对象一起销毁
    
    • 1
    • 2
    • 3
    • 4
    • 5

    NSAutoreleasePool自动释放池

    是一个类NSAutoreleasePool

    NSAutoreleasePool *pool =  [[NSAutoreleasePool alloc]init];
    
    • 1

    NSAutoreleasePool对象在调用 [pool release];的时候就会将池子内的所有对象都执行一遍release
    只执行一遍

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];//先创建池子 比池子创建更更早的变量就无法放进池子
    A *a = [[A alloc]init]autorelease];// 将a放进池子
    [pool release];
    
    • 1
    • 2
    • 3

    创建一个临时对象

    临时变量就是在创建的时候就直接加入到自动释放池里面
    一般以对象的类型作为开头的 比如[NSString stringWithFormat…]这种就是创建临时对象的类方法

    一般可以在类里面创建一个类方法 这样就会直接创建一个临时对象 并会把他加到NSAutoreleasePool里面

    @implementation A
    {
    +(id)temp
    	{
    		id f = [[self alloc]init];
    		return [f autorelease];
    	}
    }
    //在main函数中
    int main()
    {	
    	NSAutoreleasePool *pool;
    	pool = [[NSAutorelease pool alloc]init];
    	id temp = [a temp]; 
    	[pool release];
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    弱引用 __weak

    主要是防止循环引用 跟C++那个一样,如果两个share_ptr互相引用就会导致无法被释放掉
    相较于强引用 他可以引用对象
    弱引用通过存储一个只想对象的指针创建,且不保留对象

    定义

    __weak id temp;
    NSObject __weak *c,*d;
    
    • 1
    • 2

    特点

    1.引用对象后并不会成为对象的所有者 对象的引用计数不易+1或-1
    2.引用对象被释放后 弱引用会自动变成nil
    3.弱引用指向的对象一定要被另一个强引用指向 因为弱引用并不会让计数+1 所以没办法保持住一个对象
    例如:__weak A *a = [[A alloc]init];此时a的引用计数是0 马上就会被释放掉

    __unsafe_unretained 非nil化的弱指针

    相较于弱指针 这个在对象被释放之后是不会自动变成nil 会变成野指针
    在为初始化的时候__unsafe_unretained类型的变量的初始值是不确定的
    ARC不管这个类型的变量 也就是当这个变量是不被ZRC允许的时候你就可以加上这个修饰符 让ARC不去管他

    写回传 __autoreleasing

    __autoreleasing A ** a;
    的根本目的是获得一个延迟释放的对象
    比如可以向方法中传入一个未初始化的对象的引用,并且在方法中实例化该对象,在方法返回是将这个对象自动的加入到自动释放池中
    在ARC中二重指针会自动添加一个__autoreleasing的变量

    应用场景

    当我们有多个返回值时 一般是通过参数传入一个指针 将这些返回值带出来 但是不能用静态变量的指针,数组首地址的指针或内部变量的指针用于回传 这就导致需要创建一个nil或临时变量指针来完成

    -(id)initWithContentsOfFile:(NSString *)path
    	encoding:(NSStringEncoding)enc
    	error:(__autoreleasing NSError **)error//主要就是通过error去带出信息
    //调用的时候
    NSError *error = nil;
    NSString *string = [[NSString alloc]initWithContentsOfFile:@"/path/to/file.txt"
    encoding:NSUTF8StringEncoding error:&error];//在这个情况下将error直接传参就会发现这是一个静态变量指针 是不好的
    //所以ZRC会自动的变成  这部分怎么验证真是存在呢??
    NSError *error = nil;
    NSError __autotreleasing *tmpError = error;//存储nil 再将tmpError加入进自动释放池
    NSString *string = [[NSString alloc]initWithContentsOfFile:@"/path/to/file.txt"
    encoding:NSUTF8StringEncoding error:&tempError];//此时传进去的就是一个临时的指针 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    因为ARC会自动更改 但是有的时候传入二重指针并不是为了写回传

  • 相关阅读:
    1.0、C语言——初识C语言
    java毕业设计爱音乐网站Mybatis+系统+数据库+调试部署
    应用部署容器演进之路
    【附源码】计算机毕业设计SSM数据分析教学网站
    Springboot之Bean懒加载的实现详解
    R语言拟合ARIMA模型:剔除ARIMA模型中不显著的系数、设置fixed参数指定需要被剔除的系数(参数)
    vue面试相关知识
    雪糕冰淇淋经营配送小程序商城效果如何
    正点原子开拓者FPGA,程序固化下载到板子里面
    自学SLAM(6)相机与图像实践:OpenCV处理图像与图像拼接(点云)
  • 原文地址:https://blog.csdn.net/qq_43535469/article/details/126010857