weak 的实现原理

news/2024/7/20 12:58:19 标签: objective-c, weak, 原理, 面试, 内存管理
         iOS 在运行时维护着一个全局的弱引用表,该表是一个 hash 表,hash表的 key 是 weak 对象的地址,value 是指向该对象的所有 weak 指针的地址数组。   
/**
   全局的弱引用表,本质是一个hash结构,object作为key, weak_entry_t作为value
 */
struct weak_table_t {
    // 保存了所有指向特地对象的 weak指针集合
    weak_entry_t *weak_entries;
    // hash数组中元素个数
    size_t num_entries;
    // hash数组的长度,而不是元素个数。比如,数组长度可能是64,而元素个数仅存了2个
    uintptr_t mask;
    // hash冲突最大次数, 采用开放定址法解决hash冲突
    uintptr_t max_hash_displacement;
};
        以下述代码为例:
NSObject * obj =  [[NSObject alloc] init];

__weak NSObject *p1 = obj;
__weak NSObject *p2 = obj;

objc_object ** referrer1 = &p1;
objc_object ** referrer2 = &p2;

[obj release];

         hash表的key为obj,hash表的值weak_entries的referers属性被赋值为[referrer1, referrer2];

        当weak修饰的对象obj被销毁时,iOS在运行时会从哈希表中查找到所有指向此对象的 weak 指针,并将其全部置为空 nil,即通过执行*referrer1 = NULL和*referrer2 = NULL,实现将p1和p2置为NULL。
 
weak_clear_no_lock(weak_table_t *weak_table, id referent_id) {
    // 在weak_table中对应的weak_entry_t
    objc_object *referent = (objc_object *)referent_id;
    weak_entry_t *entry = weak_entry_for_referent(weak_table, referent); 
    weak_referrer_t referrers = entry->referrers;
    int count = TABLE_SIZE(entry);

    for (size_t i = 0; i < count; ++i) {
        objc_object **referrer = referrers[i]; 
        if (referrer) {
            // 如果weak指针确实弱引用了对象 referent,则将weak指针设置为nil
            if (*referrer == referent) { 
                *referrer = nil;
            }
        }
    }
}

        iOS在ARC下通过引入weak标识, 大大减少了以前retain或assign标识的对象在被销毁后可能出现野指针的情况,进而有效提升了代码健壮性。


http://www.niftyadmin.cn/n/5398599.html

相关文章

Java 继承与多态:代码重用与灵活性的巧妙结合

Java 继承&#xff08;子类和超类&#xff09; 在 Java 中&#xff0c;可以从一个类继承属性和方法到另一个类。我们将“继承概念”分为两类&#xff1a; 子类&#xff08;child&#xff09;: 从另一个类继承的类 超类&#xff08;parent&#xff09;: 被继承的类 要从一个类…

关于CSS常见选择器应用的基础教程

在网页开发中&#xff0c;CSS选择器是非常重要的一部分&#xff0c;它们用来指定你想要样式化的HTML元素。熟练掌握各种选择器的用法可以帮助你更有效地实现网页布局和设计。本文将介绍一些常见的CSS选择器&#xff0c;并演示它们的基本用法及应用场景。 一、元素选择器&#…

jenkins部署maven项目

流程&#xff1a; jenkins从代码仓库读取代码&#xff0c;将代码文件放入jenkins的工作空间&#xff0c;将jenkins工作空间的代码进行打包&#xff0c;将jar包远程发送给服务器。 一&#xff1a;所需插件二&#xff1a;Tools 三&#xff1a;System&#xff1a; 配置ssh连接的…

(案例贴2) html+css 倒计时器

欢迎大家使用这个计时器噢 老哥直接附代码咯. timer.html <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0">&l…

Flutter学习7 - Dart 泛型

1、泛型类 //泛型类 class Cache<T> {final Map<String, T> _cache {};void saveData(String key, T value) {_cache[key] value;}//泛型方法T? getData(String key) {return _cache[key];} }void main() {Cache<int> cache1 Cache();const String name…

微信小程序 --- 常用样式和组件

常用样式和组件 1. 组件和样式介绍 在开 Web 网站的时候&#xff1a; 页面的结构由 HTML 进行编写&#xff0c;例如&#xff1a;经常会用到 div、p、 span、img、a 等标签 页面的样式由 CSS 进行编写&#xff0c;例如&#xff1a;经常会采用 .class 、#id 、element 等选择…

AI新秀Mistral:“Open AI“ 新时代

最近互联网出现不少类似“下一代openai”、“GPT-4最强竞品”、“法国AI独角兽”、“欧洲的OpenAI”、“微软新宠儿”.... 的文章&#xff0c;都会附带一张图片&#xff0c;就是下面这张&#xff1a; 那么到底发生了什么&#xff0c;出来个什么东西呢&#xff1f;就是本文的主…

springboot+vue前后端分离适配cas认证的跨域问题

0. cas服务搭建参考:CAS 5.3服务器搭建_cas-overlay-CSDN博客 1. 参照springsecurity适配cas的方式, 一直失败, 无奈关闭springssecurity认证 2. 后端服务适配cas: 参考前后端分离项目(springbootvue)接入单点登录cas_前后端分离做cas单点登录-CSDN博客 1) 引入maven依赖 …