swift闭包底层本质

news2024/12/23 20:03:22

swift学习笔记

闭包底层原理

1、函数赋值给一个变量
func getFn(_ a: Int) -> Int {
  return a + 1
}

let funcVar = getFn
  • 当在把一个函数赋值给一个变量funcVar的时候,funcVar变量会存储两个东西
    • funcVar总共占用16个字节
    • 前八个字节存储着getFn的函数地址
    • 后八个字节存储着0
      • 这种情况下暂时是没用到的,因此是0这种空值
      • 当在闭包当中就有大大的用处
2、 闭包捕获一个变量时赋值给一个变量
func getFn() -> (Int) -> (Int) {
  var num = 0
  func plus(_ a: Int) -> Int {
    num += a
    return num
	}
  
  return testClosure
}

let plus = getFn()
plus(1)
plus(2)
  • 当把捕获一个变量的闭包赋值给一个变量plus的时候,plus变量也同样会存储两个东西
    • plus总共占用16个字节
    • 前八个字节存储着getFn的函数地址
    • 后八个字节存储捕获到的num的信息,并且此信息存储在堆空间
      • 此时的num已经被包装成一个对象了
      • 其拥有24个字节
      • 前八个字节存储着类似isa的东西
      • 中间八个字节存储着引用计数
      • 最后八个字节就是num
  • 当在调用plus(1)的时候,会找到其存储的前八个字节,也就是闭包的函数地址,进行函数调用
  • 调用的时候,会传入两个参数
    • 一个是1
    • 另一个就是捕获的堆空间的num

内存信息

3、闭包捕获多个变量时赋值给一个变量
func getFn() -> (Int) -> (Int) {
    var num = 5
    var num1 = 6
    func plus(_ a: Int) -> Int {
        num += a
        num1 += 1
        return num + num1
    }
    
    return plus
}

let plus = getFn()
plus(1)
  • 当把捕获两个变量的闭包赋值给一个变量funcVar的时候,funcVar变量也同样会存储两个东西
    • plus总共占用16个字节
    • 前八个字节存储着getFn的函数地址
    • 后八个字节存储捕获到的num和num1的信息,并且此信息存储在堆空间
      • 此时的num和num1共同被被包装成一个对象了
      • 其拥有32个字节
      • 第一个八字节存储着类似isa的东西
      • 第二个八字节存储着引用计数
      • 第三个八字节存储的是被包装成对象的num信息
        • 拥有24个字节
        • 前八个字节存储着类似isa的东西
        • 最后八个字节存储的就是num
      • 第三个八字节存储的是被包装成对象的num1信息
        • 拥有24个字节
        • 前八个字节存储着类似isa的东西
        • 最后八个字节存储的就是num1
  • 当在调用funcVar(1)的时候,会找到其存储的前八个字节,也就是闭包的函数地址,进行函数调用
  • 调用的时候,会传入两个参数
    • 一个是1
    • 另一个就是捕获的堆空间的num

内存信息

4、闭包捕获多个值,并且返回多个函数
func getFn() -> ((Int) -> (Int), (Int) -> (Int)) {
    var num = 5
    var num1 = 6
    func plus(_ a: Int) -> Int {
        num += a
        num1 += 1
        return num + num1
    }
    func minus(_ a: Int) -> Int {
        num += a
        num1 += 1
        return num - num1
    }
    
    return (plus, minus)
}

let (plus, minus) = getFn()
plus(1)
plus(2)
minus(1)
minus(2)
  • 这种情况就跟上面那种情况是一样的。可以理解成每返回一个闭包就是有一个上面那种情况的内存信息
  • 因此这里返回两个闭包,就是有两个上面一样的内存信息
  • 只是他们指向的num对象信息相当于是一样的

内存信息1
内存信息2

5、闭包捕获class对象
func getObjFn() -> (Int) -> (Int) {
    var num = 5
    var obj = FnObj()
    obj.a = 3
    func plus(_ a: Int) -> Int {
        num += a
        obj.a += 1
        return num + obj.a
    }
    
    return plus
}

let plus = getObjFn()
plus(1)
  • 对变量的捕获方式跟捕获普通变量几乎一样
  • 只是捕获class对象的时候,不会再次对class对象进行包装
  • 因为要放在堆上面,因此普通变量会包装成class对象
  • class对象本身就是class对象,因此不需要再次包装
  • 因此其实对class对象的捕获相对来说更简单

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/531901.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

浅聊一下NTP

浅聊一下NTP 仅了解,没实践过NTP 文章目录 浅聊一下NTP1.什么是NTP2.基本原理3.工作模式1.单播服务器/客户端模式2.对等体模式3.广播模式4.组播模式 4.NTP数据报文 1.什么是NTP 网络时间协议NTP(Network Time Protocol)是TCP/IP协议族里面…

PowerShell系列(三):PowerShell发展历程梳理

目录 1、PowerShell 1.0 版本特性 2、PowerShell 2.0 版本特性 3、PowerShell 3.0 版本特性 4、PowerShell 4.0 版本特性 5、PowerShell 5.0 版本特性 6、PowerShell 5.1 版本特性 7、PowerShell6.0 Core 版本特性 8、PowerShell7.0 Core 版本特性 今天给大家聊…

openAI图像生成开发文档

图像生成 了解如何使用我们的 DALLE 型号 介绍 图像 API 提供了三种与图像交互的方法: 根据文本提示从头开始创建图像根据新的文本提示创建现有图像的编辑创建现有图像的变体 本指南介绍了使用这三个 API 终结点的基础知识以及有用的代码示例。要了解它们的实际…

海外网红营销vs国内网红营销:2023年市场洞察与策略差异

随着互联网和社交媒体的迅猛发展,网红营销已经成为一种炙手可热的推广方式。无论是国内还是海外,网红营销都在不断演变和创新,以满足广告主和品牌的需求。然而,海外网红营销和国内网红营销之间存在一些显著的区别。本文Nox聚星将和…

第三章 哈希表

目录 一、有效的字母异位词1.1 赎金信1.2 字符异位词分组1.3 找到字符串中所有字母异位词 二、两个数组的交集2.1 两个数组的交集 II 三、快乐数四、两数之和五、四数相加 II六、三数之和七、四数之和 哈希解决问题一般有三种数据结构供选择: 数组map(映…

图解LeetCode——234. 回文链表

一、题目 给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。 二、示例 2.1> 示例 1: 【输入】head [1,2,2,1] 【输出】true 2.2> 示例 2: 【输…

[Android Studio Tool]在Android Studio项目中如何使用CSV文件

文章目录 在Android Studio项目中如何使用CSV文件1. 前情提要:CSV文件的准备2. CSV文件在安卓项目一般存放在什么位置?3. Android Studio处理CSV文件的常用插件?4. 怎么调整Android Studio中对GBK编码的CSV文件的处理?以下是一个代…

就业内推 | 国企招运维工程师,红帽认证、华为认证优先

01 厦门中盾安信科技有限公司 🔷招聘岗位:应用运维工程师(中级) 🔷职责描述: 1、负责平台应用系统的安装、配置、日常巡检、维护、故障的处理; 2、负责平台服务相关应用的部署、配置、日常巡检…

Java面试知识点(全)- Java IO知识点详细

Java面试知识点(全) 导航: https://nanxiang.blog.csdn.net/article/details/130640392 注:随时更新 从数据传输方式理解IO流 从数据传输方式或者说是运输方式角度看,可以将 IO 类分为: 字节流, 字节流读取单个字节,字符流读取单…

mock模拟数据 ,UmiJS构建项目

Mock是一个用于模拟数据的JavaScript库,可以根据需要生成各种数据类型的模拟数据,可以配合json server使用 并且可以使用拦截ajax请求来模拟后端API接口。 JSON Server则是一个使用JSON文件来模拟RESTful API的工具 > 默认安装到运行环境&#xff1…

MYSQL索引、事务、存储引擎

一、索引 索引是一个排序的列表,包含字段的值和相应的行数据的物理地址 作用:加快表的查询速度,可以对字段排序 如何实现:没有索引的情况,要查询某行数据,需要先扫描全表来定位某行数据。有索引后会通过…

java ThreadLocal

private ThreadLocal threadLocal new ThreadLocal(); threadLocal.set(0); (int) threadLocal.get(); 上面三行代码分别是定义、赋值和取值。 介绍: 我们只需要实例化对象一次,并且也不需要知道它是被哪个线程实例化。虽然所有的线程都能访问到这个T…

【Vue】学习笔记-Vue CLI $nextTick 过渡与动画

$nextTick 这是一个生命周期钩子 this.$nextTick(回调函数) 在下一次DOM更新结束后执行其指定的回调 什么时候用:当数据改变后,要基于更新后的新DOM进行某些操作时,要在nextTick所指定的回调函数中执行。 使用$nextTick优化Todo-List src/co…

winform-SunnyUI控件解决大小位置变化

文章目录 前言问题种类使用SunnyUI解决控件DPI问题(分辨率问题)1.添加配置文件app.manifest2.将配置文件中dpiAware打开3.添加uiStyleManager1控件并将控件中DPIScale设置为true4.效果图 使用FlowLayOutPanel解决控件边距问题1.问题样式2.使用FlowLayOut…

Grafana系列-统一展示-12-RED Method Dashboard

系列文章 Grafana 系列文章 概述 目前关于监控指标, 主流的有 3 个方法(Method): RED : Rate(访问速率), Errors(错误), Duration(响应时长) - 由 tom_wilkie 引入USE : Utilization(利用率…

TEMPUS FUGIT: 2

环境准备 靶机链接:百度网盘 请输入提取码 提取码:5i9p 虚拟机网络链接模式:桥接模式 攻击机系统:kali linux 2022.03 信息收集 1.对靶机进行端口和服务的扫描 nmap -sV -p- -A 10.10.10.130 可以看到22端口是关闭的 2.用…

线段树-哈工大数据结构与算法作业

title: 线段树-哈工大作业 date: 2023-05-16 11:42:26 tags: 数据结构与算法 线段树 问题: 区间查询求和问题:给定一个含有n个整数序列的数组A,查询任意区间最大值与区间和的复杂度为O(n),若进行m次查询,则总的复杂度为O(mn)。…

深析AutosarNM 网络管理

深析AutosarNM 网络管理 深析AutosarNM 网络管理1. AutosarNM 网络管理相关的专业术语2. 各种模式下的各种状态下,报文的收发情况汇总如下表:3. AutosarNM网络管理使用的时间参数:4. AutosarNM网络管理唤醒请求(Wake Up Request)5. ​​​​​…

MySQL 5.7数据库下载与安装教程

说明: 安装环境:Win10 64位 软件版本:MySQL 5.7.35 解压版 一.下载 点击下载地址: MySQL :: Download MySQL Community Server (Archived Versions) https://downloads.mysql.com/archives/community/ 选择合适的版本下载 绿色框框 是正式版&#xff0…

第02讲:SpringCloudStream

一、什么是SpringCloudStream SpringCloudStream是SpringCloud的一个子项目,他提供了一套更加通用的操作MQ的解决方案 Destination Binder(目标绑定器) :微服务与消息中间件通信的组件Destination Bindings(目标绑定&…