• 《Objective-C 高级编程》 1.2.3节 alloc/retain/release/dealloc 实现——学习总结


    《Objective-C 高级编程》 1.2.3节 alloc/retain/release/dealloc 实现——学习总结

    更新记录

    时间 版本修改
    2020年4月23日 初版
    2020年4月25日 更正:苹果的实现方式并不是在NSObejct基类中用一个字段记录引用计数,而是使用散列表的方式

    前言

    • 本人在阅读《Objective-C 高级编程》 1.2.3节 alloc/retain/release/dealloc实现这个章节时,有一个细节一只没搞懂
    • 这个问题阻塞了我的阅读进度,直至后续和一位好友交流时才彻底搞懂了这个问题(虽然本质确实是个很简单的问题)。

    我的疑惑

    • 按照我们之前泛读该书的得到常用结论,大致如下
      • ARC模式下,NSObejct使用引用计数的方式自动管理内存
      • 其原理大致如“N个人进入办公室,开灯,N个人离开办公室,关灯”这个鲜明的例子
      • 所以,生成一个NSObject对象,其引用计数应该是1。
    • 我的问题
      • 但是当我看到下面release的实现代码时,感觉到非常的困惑
      - (void)release {
          if (NSDecrementExtraRefCountWasZero(self)) {
              [self dealloc];
          }
      }
      
      //这是一个C语言的函数
      BOOL NSDecrementExtraRefCountWasZero(id anObject) {
          if (((struct obj_layout *)anObject)[-1].retained == 0) {
              return YES;
          } else {
              ((struct obj_layout *)anObject)[-1].retained--;
              return NO;
          }
      }
      
      • 为1的时候应该就要释放才对了呀,为什么引用计数为1的时候,还要执行减1操作,变成0呢?

    指点迷津

    • 之所以有这样的困惑,是因为犯了一个先入为主的错误:
      • 真实的引用计数一定是从1计数的吗?0是代表什么呢?
    • 看到作者给出的retainCount函数:
      - (NSUInteger)retainCount {
          return NSExtraRefCount(self) + 1;
      }
      
      //C语言函数
      inline NSUInteger NSExtraRefCount(id anObject) {
          return ((struct obj_layout *)anObject)[-1].retained;
      }
      
    • 也就是说,结构体的成员变量retained是从0开始计数的。
      • 初始化对象的时候,初始化为0,就已经表示这个对象目前被持有一次了。
      • 如果再被持有一次,会+1,变成1
      • 如果这个时候释放,见上述的NSDecrementExtraRefCountWasZero函数,因为等于0,所以调用dealloc销毁了该对象。
      • retainCount函数返回值,手动加上了1,契合了人类本身的思考方式。(所以千万不要像我一样被误导了)
    • 注意
      • 这里是作者剖析 GNUstep 源代码得来的,自动引用计数的实现方式,和苹果,以及由于时光匆匆,实现机制不一定完全一样。但是基本思想是不变的。(目前苹果最新的实现方式,是利用散列表记录每个对象的引用计数,不在作为NSObject类的字段,减小了对象的内存)。

    后记

    • 搞清楚每一个细节,才能一点一点堆砌基础,乃至堆起整个知识体系。
  • 相关阅读:
    英语阅读重点单词总结
    Redis 应用
    Python 列表[::-1]翻转
    golang数据类型
    golang变量
    k8s 容器控制台日志收集
    css显示模式
    css选择器
    css样式引入
    GIL锁
  • 原文地址:https://www.cnblogs.com/HelloGreen/p/12764806.html
Copyright © 2020-2023  润新知