当前位置: 首页 > news >正文

探秘block原理

01

概述

iOS开发中,block大家用的都很熟悉了,是iOS开发中闭包的一种实现方式,可以对一段代码逻辑进行封装,使其可以像数据一样被传递、存储、调用,并且可以保存相关的上下文状态。

很多block原理性的文章都比较老,里面讲的一些知识已经过时,这里用新版的iOS SDK再梳理一遍block原理,也是和大家一起对已有知识做一次复习。

02

内存布局

block本质上可以理解为结构体,对于结构体的内存布局,先用一张图来表示一下,图中字段顺序按照布局的先后顺序:

  • isa:block也有isa,从内存结构上也属于对象,isa指向的是block的类对象,类对象例如__NSMallocBlock__,后续文章会讲到;

  • flags:用于存储一些标志位信息,例如是否捕获外部变量;

  • reserved:系统保留字段,后续可能会用于一些编译优化标志位,或者存储一些临时变量的处理;

  • invoke:函数指针,指向了block要执行的函数地址,也就是block代码块对应的函数地址;

  • descriptor(现在叫desc):指向block_desc_0,包含block大小、捕获的外部变量布局信息、增加引用计数和销毁的相关函数指针;

  • variables:block捕获的外部变量。

e18475710e99f3b78225d8e2d40448b3.jpeg

03

类型

由于block也是对象,可以通过class方法获取到其类型,也就是类对象。block有下面三种类型:

  • __NSGlobalBlock__,没有访问auto变量的block,访问static变量是没问题的。这种类型的变量并没有什么意义,如果不需要用到auto变量,写成方法就可以满足需求;

  • __NSStackBlock__,在MRC环境下,访问了auto变量,会默认被放在栈区。需要手动copy到堆区,ARC环境下会在访问auto变量后,会自动拷贝到堆区;

  • __NSMallocBlock__,由开发者自己管理内存,不会由系统来释放。

block的分配主要是在三个区域,堆区、栈区、全局区,全局区的数据存储在数据段。

block在不同的场景会存在不同的内存区域中,在MRC中创建一个block首先是在__NSStackBlock__内存中的,然后我们使用copy方法将block拷贝到__NSMallocBlock__内存中进行内存管理。后来在ARC中系统已经帮我们做好了copy的操作,创建的block会自动copy__NSMallocBlock__内存中,堆区的block也有引用计数的概念。如果这个block中没有用到任何外部参数,系统会将这个block存放在__NSGlobalBlock__内存中。

c913a0afef72bdbd98f71395736359ac.jpeg

并且block也有继承关系,以下面TestBlock的实例来说,其父类是__NSGlobalBlock__,所有block的父类是NSBlock,并且NSBlock继承自NSObject类。在更早一些的iOS系统中,__NSGlobalBlock__NSBlock之间,还会有一层__NSGlobalBlock的关系(后面没有下划线)。

e9e860f99ca7d209648e62b2a95f8137.jpeg

04

转换C++

下面,我们通过clang命令将block转为结构体,来分析下其具体实现。虽然这并不是最终运行在iOS系统上的代码,其等于一种中间表现形式,后续编译链接优化才会形成运行在手机上的ipa包,但对于我们了解block的实现原理有很大帮助。

4.1转换命令

xcrunXcode用于查找和执行相关命令行的工具集,可以更好的执行clang命令,减少报错。

xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc -fobjc-arc [源文件路径] -o [目标文件路径]

clang命令有下面这些关键参数:

  • -fobjc-arc:如果项目是ARC或者ARCMRC混编的环境,需要通过此参数修饰,表示按ARC的方式进行转换,如果不需要ARC环境可以忽略;

  • -x objective-c++:此参数上面没用,如果包含Objective++源文件的时候,需要用到此参数,以确保clang可以区分OCC++代码;

  • -rewrite-objc:告诉clangC++的方式重写出来,包含的上层代码,clang会以底层代码的方式进行展现;

  • [目标文件路径]:非必传参数,不传的话默认在当前目录生成一个同名的cpp文件,例如main.m对应main.cpp

4.2转换示例

下面在main.m中实现了一个很简单的block,并且没有捕获任何外部变量,通过clang命令查看C++代码,观察block的具体实现原理。

00f1462166473024588d9fd02489c95a.jpeg

转换后将C++源文件拉到最下面,可以看到main函数以及TestBlock的实现,main函数中有很多转义代码,删掉后梳理逻辑会更清晰。

f7c52e76e5d0f1a69d472a96e9dd30f2.jpeg

05

结构体

5.1基础结构

转换后的代码看着比较复杂,但我们只看关键信息,__main_block_impl_0构造函数也可以去掉,整理后就是下面三个结构体。在不包含外部变量和__block的前提下,block结构体各个字段就这么简单,关键就是isaBlock_sizeFuncPtr这三个。

5184de03fe7c376000daf74131afb8a9.jpeg

我们也可以打印block结构体相关字段,但由于block的结构体并没有声明在某个.h文件中,所以需要我们讲clang转换后的结构体粘到对应的文件中,做显示声明。随后用__bridge的方式,将block对象桥接为自己声明的结构体,即可打印对应字段。

44e51b22f299d5b26fbae4462f3b9c28.jpeg

结构体中impl.FuncPtr存储的就是回调函数地址,从地址可以看出是一个虚拟地址,block结构体都存储在堆区。

f3cbcb3a80da27952f3524550dcac601.jpeg

5.2调用部分

看完block结构体的定义,我们来到main函数中,看block的实现和调用转换后是什么样的。将main函数中block相关的转换都去掉,结果如红圈部分。本质上就是两步,第一步是调用__main_block_impl_0的结构体构造函数,第二步是调用结构体的函数指针。

ae8765f95f711b319acf44797c17b6d0.jpeg

第一行main函数中调用的构造方法,是__main_block_impl_0结构体声明的C++构造函数,因为我们创建的是一个最简单block,可以看到block的存储区域是在stack栈区的。即main函数调用完,block生命周期就会结束。

81052833ccb9918733af2aabb3a32994.jpeg

__main_block_impl_0构造函数有两个参数,第一个红圈部分就是传入函数指针地址,函数对应的就是block内部的实现代码。第二个参数是__main_block_desc_0_DATA结构体,其定义为__main_block_desc_0,并且默认实现第一个参数传0,第二个参数是block结构体的大小,结构体为__main_block_impl_0 block自身的结构体大小。第三个参数有默认值,可以不传。

0fb6d3895960933a3d6590f8fb0a690b.jpeg

__main_block_desc_0结构体是一种紧凑型的写法,在声明__main_block_desc_0结构体后,紧接着声明了一个名为__main_block_desc_0_DATA的变量,变量类型为静态变量,并且实现了初始化相关代码。

e436962389273ae83f4dd6418f28067c.jpeg

在执行block的代码位置,可以看到并不是block->impl.FuncPtr的方式调用,而是直接block->FuncPtr的方式调用,中间少了一步。

严谨些来说应该加上impl,但不加也不会出问题。这是因为,如果看未删除转换代码的原始clang代码,可以看到block是被转换为__block_impl的,也就是说被当做__block_impl看待的。如果再结合__main_block_impl_0的结构体定义来看,__block_impl在成员变量的第一位,所以访问FuncPtr是没有问题的,只要不访问Desc就是可以的。

06

外部变量

6.1值类型

如果在block的调用中加一个外部变量,那结构体将会是怎样的?

f5260e86bcd1db4a6691b3d1485b8f04.jpeg

通过clang命令可以可以看到,转换后的__main_block_impl_0中增加了一个同名字段,这很简单没必要过多解释。在__main_block_impl_0构造函数中传入,通过冒号后的初始化列表对value参数进行初始化。

71a50a73be623393a2c6501c93cd7075.jpeg

后面传参和使用,就都是结构体赋值和取值逻辑,很简单。

94f5bfe29b82fe787deee58064b04390.jpeg

6.2值传递

下面这种写法,在block的使用中很容易踩坑。在block中使用value参数,并且打印value参数,发现结果为1,而不是2

b56fcbf676dbea7dbddd0000e1324668.jpeg

通过C++源码我们可以看到,这是因为如果block引用的外部变量是值类型,会采取直接复制值的方式,而不是指针引用。

a2d50b3f0432de4a7f16455ff65cea20.jpeg

想解决这个问题也很简单,通过__block修饰一下值类型,即可实现blockvalue的值和外部value参数统一。

5442504f43156c89f510a36b4c548e95.jpeg

6.3静态变量

我们看一下,如果捕获的是一个static修饰的静态变量,其结构体会是什么实现。

0db25bc636677e044134ce146939cd4f.jpeg

转换为C++代码后,可以看到原来的值传递变成了地址传递,__main_block_impl_0value的引用是指针引用,在main函数中将value的地址传入。如果被static修饰的本身就是一个对象,对象是通过指针引用的,在block的结构体中就是两个星号引用。也就是NSObject **obj

4dbc42fa4f8fc4699a4b7083cc57a9dc.jpeg

正是由于静态变量地址传递的实现,在block内可以对静态变量直接进行更改,而无需用__block进行修饰。

737894d22f7b7ad64acd752ea7d789d9.jpeg

6.4全局变量

如果把value改为全局变量,结构体会有什么变化呢?

65c56008740b61e373f44ded28eeb87a.jpeg

因为全局变量的作用域很大,所以并不需要block进行单独持有即可访问,结构体并不会新增字段。

51f04513f76cc4e9ca9233f123b55202.jpeg

6.5对象类型变量

如果block中引用的是对象,而不是基础数据类型,结构体会是什么定义呢?

c4927fcbb5e2603ec6bfcf64770b4008.jpeg

执行clang命令,执行完成后结构体是下图的,下面代码去掉了转换,以及整理过代码。可以看到多了两个函数指针,__main_block_copy_0__main_block_dispose_0

copy的实现__main_block_copy_0为例,执行后会调用Block_object_assign的实现,在实现中系统会根据person的引用方式,__strong__weak__unsafe_unretained,是强引用还是弱引用,调用对应的内存管理方法。

__main_block_dispose_0函数在block从堆区移除的时候被调用,调用dispose时会调用实现Block_object_dispose函数,函数中会根据person的引用方式,进行对应的减少引用计数或释放操作。

copydispose两个函数都有一个3的参数,这个参数是一个标志位,表示外部变量类型。这里是BLOCK_FIELD_IS_OBJECT表示一个对象类型,也有BLOCK_FIELD_IS_WEAK表示weak引用的变量,BLOCK_FIELD_IS_BLOCK表示block类型的变量等。

25327a0ccd7b9c3b385e0207026a020d.jpeg

07

结尾

感谢大家能把文章读完,这篇文章并不会包含__block__weak相关知识,为了更系统的了解这两部分,后面会新出一篇文章整体来讲一下,敬请期待~

相关文章:

探秘block原理

01 概述 在iOS开发中,block大家用的都很熟悉了,是iOS开发中闭包的一种实现方式,可以对一段代码逻辑进行封装,使其可以像数据一样被传递、存储、调用,并且可以保存相关的上下文状态。 很多block原理性的文章都比较老&am…...

Unity2D初级背包设计后篇 拓展举例与不足分析

Unity2D初级背包设计中篇 MVC分层撰写(万字详解)-CSDN博客、 如果你已经搞懂了中篇,那么对这个背包的拓展将极为简单,我就在这里举个例子吧 目录 1.添加物品描述信息 2.拓展思路与不足分析 1.没有删除只有丢弃功能,所以可以添加垃圾桶 2.格…...

云计算基础,虚拟化原理

文章目录 一、虚拟化1.1 什么是虚拟化1.2 虚拟化类型 二 、存储虚拟化2.1 存储指标2.2 存储类型2.3 存储协议2.4 RAID 三、内存 i/O虚拟化3.1 内存虚拟化基本概念地址空间转换原理内存共享与隔离原理 3.2 I/O 虚拟化基本概念模拟(Emulation)方式半虚拟化…...

Android13工具修改wifi mac地址以后没有更新的问题

Android13系统在通过烧写工具更新修改wifi mac地址以后,在系统设置里面查看wifi mac地址还是之前的,没有更新。 原因:android13 系统中packages\modules\Wifi\service\ServiceWifiResources\res\values\config.xml新增了"config_wifiSav…...

Jmeter_后置处理beanshell

背景:调用Eolinker接口,统计接口测试用例的完成情况,并写入excel文件; 1、调用登录接口,JSON提取器提取接口返回的accessToken,再封装到HTTP信息头管理器中; 2、请求工作空间列表接口&#xff0…...

熵与交叉熵:从不确定性角度理解 KL 散度

从不确定性减少视角理解KL散度 损失函数相关文章(置顶) 1. KL 散度:多维度解读概率分布间的隐秘 “距离” 2. 熵与交叉熵:从不确定性角度理解 KL 散度 3. 机器学习、深度学习关于熵你所需要知道的一切 本文核心 由于熵表征不确定…...

HarmonyOS鸿蒙开发 弹窗及加载中指示器HUD功能实现

HarmonyOS鸿蒙开发 弹窗及加载中指示器HUD功能实现 最近在学习鸿蒙开发过程中,阅读了官方文档,在之前做flutter时候,经常使用overlay,使用OverlayEntry加入到overlayState来做添加悬浮按钮、提示弹窗、加载中指示器、加载失败的t…...

KG-CoT:基于知识图谱的大语言模型问答的思维链提示

一些符号定义 知识图谱实体数量: n n n 知识图谱中关系类型数量: m m m 三元组矩阵: M ∈ { 0 , 1 } n n m \textbf{M} \in \{0, 1\}^{n \times n \times m} M∈{0,1}nnm, M i j k 1 M_{ij}^k 1 Mijk​1则说明实体 i i i和实…...

(2024,影响 LLaVA 性能的因素,LLM 模型规模,视觉输入配置(网格/token 数),AnyRes,数据量/质量)

LLaVA-NeXT: What Else Influences Visual Instruction Tuning Beyond Data? 目录 0. 简介 1. 架构 1.1 语言模型 1.2 视觉编码器 2. 视觉表示 2.1 训练时分辨率和 token 数量配置 2.2 LLM 扩展的有效性 2.3 放大原始图像 2.4 推理时分辨率和 token 数量配置 2.5 池…...

Vue3 网络请求

文章目录 Vue3 网络请求CORS问题ajaxfetchaxios Vue3 网络请求 CORS问题 同源:指的是当前用户所在的URL与被请求的URL的协议名、域名、端口必须完全相同。一旦有一个或多个不同,就是非同源请求,也就是我们经常说的跨域请求,简称…...

全方位解读消息队列:原理、优势、实例与实践要点

全方位解读消息队列:原理、优势、实例与实践要点 一、消息队列基础认知 在数字化转型浪潮下,分布式系统架构愈发复杂,消息队列成为其中关键一环。不妨把消息队列想象成一个超级“信息驿站”,在古代,各地的信件、物资运…...

Java-数据结构-栈与队列(StackQueue)

一、栈(Stack) ① 栈的概念 栈是一种特殊的线性表,它只允许固定一端进行"插入元素"和"删除元素"的操作,这固定的一端被称作"栈顶",对应的另一端就被称做"栈底"。 📚 栈中的元素遵循后…...

Transformer入门教程全解析(一)

一、开篇:走进Transformer的奇妙世界 在当今深度学习领域,Transformer 无疑是一颗璀璨的明星,它如同一股强大的变革力量,席卷了自然语言处理(NLP)乃至更多领域。从机器翻译到文本生成,从问答系…...

拼音读音基础

文章目录 一、音节1、结构2、声母3、韵母 二、声调 拼音读音往往被认为跟应试考试相关,学会正常交流口语以后不再进行关注,其实还是有必要了解细节、查漏补缺。 一、音节 1、结构 音节 声母 韵母;一个音节基本等于一个汉字; 2、…...

Qt 坐标系统和坐标变换

一、概述:1、QPainter在QPaintDevice上绘图的默认坐标系统是,原点(0,0)在左上角,x轴正方向水平向右,y轴正方向竖直向下的坐标系。 2、为了绘图的方便,QPainter提供了一些坐标变换的功能,通过平移、旋转、缩放等坐标变…...

【redis】ubuntu18安装redis7

在Ubuntu 18下安装Redis7可以通过以下两种方法实现:手动编译安装和使用APT进行安装。 Ubuntu 18系统的环境和版本: $ cat /proc/version Linux version 4.15.0-213-generic (builddlcy02-amd64-079) (gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)…...

Outlook 网页版一直提示:检测到重复的重定向

Outlook 网页版提示“检测到重复的重定向”通常是由于浏览器缓存、Cookie问题或浏览器插件引发的。可以按照以下步骤进行排查和解决: 1. 清除浏览器缓存和 Cookie 在浏览器设置中找到清除浏览数据的选项。勾选“缓存文件”和“Cookies”相关选项,然后清…...

初级前端面试题 - js

前言:众所周知,HTML,CSS,JS是学习前端所必备的。js的基础学好了,框架类的vue,react等都会接受的很快,因此js是前端很总要的一个部分,这篇文章将会结合面试题,对js的知识点进行总结 号外号外,这是…...

matlab的绘图的标题中(title)添加标量以及格式化输出

有时候我们需要在matlab绘制的图像的标题中添加一些变量,这样在修改某些参数后,标题会跟着一块儿变。可以采用如下的方法: x -10:0.1:10; %x轴的范围 mu 0; %均值 sigma 1; %标准差 y normpdf(x,mu,sigma); %使用normpdf函数生成高斯函数…...

51单片机——串口通信(重点)

1、通信 通信的方式可以分为多种,按照数据传送方式可分为串行通信和并行通信; 按照通信的数据同步方式,可分为异步通信和同步通信; 按照数据的传输方向又可分为单工、半双工和全双工通信 1.1 通信速率 衡量通信性能的一个非常…...

mapbox基础,style样式汇总,持续更新

👨‍⚕️ 主页: gis分享者 👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍⚕️ 收录于专栏:mapbox 从入门到精通 文章目录 一、🍀前言二、🍀根属性2.1 so…...

用AI技术提升Flutter开发效率:ScriptEcho的力量

引言 在当今快速发展的技术时代,Flutter作为一种跨平台开发框架,正在越来越多的开发者中崭露头角。它不仅能够为开发者提供一套代码同时部署到iOS和Android平台的解决方案,还能帮助企业节省人力成本和开发时间。然而,对于新手开发…...

Java阶段四04

第4章-第4节 一、知识点 CSRF、token、JWT 二、目标 理解什么是CSRF攻击以及如何防范 理解什么是token 理解什么是JWT 理解session验证和JWT验证的区别 学会使用JWT 三、内容分析 重点 理解什么是CSRF攻击以及如何防范 理解什么是token 理解什么是JWT 理解session验…...

vivado 时钟指南

时钟指南 每个 FPGA 架构都为时钟提供有专用资源。掌握 FPGA 架构中的时钟资源,使您能够规划好自己的时钟,从而实现时钟 资源的最佳利用。大多数设计无需您了解这些细节。但如果您能够控制布局,同时对每个时钟域上的扇出有良好的思 路&a…...

git项目提交步骤(简洁版)

1.创建仓库 2.填写 信息 3.点击这个按钮 4.找到要上传的文件,在目录内右键点击 5.依次执行命令 在命令窗口中输入:git init 复制仓库地址: 在命令窗口中输入:git remote add origin 仓库地址 在命令窗口中输入:…...

Jmeter-压测时接口如何按照顺序执行

Jmeter-压测时接口如何按照顺序执行-临界部分控制器 在进行压力测试时,需要按照顺序进行压测,比如按照接口1、接口2、接口3、接口4 进行执行 查询结果是很混乱的,如果请求次数少,可能会按照顺序执行,但是随着次数增加…...

模式识别-Ch5-线性判别函数

Ch5 线性判别函数 文章目录 Ch5 线性判别函数引言:生成模型 vs判别模型生成模型 vs 判别模型判别模型分类 线性判别函数与决策面线性判别函数两类情况下的决策多类问题下决策 多类情形-线性机器线性决策面优缺点 广义线性判别函数例:二次判别函数例1: 1-…...

数据结构二叉树-C语言

数据结构二叉树-C语言 1.树1.1树的概念与结构1.2树的相关术语1.3树的表示1.4树形结构实际运用场景 2.二叉树2.1概念与结构2.2特殊的二叉树2.2.1满二叉树2.2.2完全二叉树 2.3二叉树存储结构2.3.1顺序结构2.3.2链式结构 3.实现顺序结构的二叉树4.实现链式结构二叉树4.1前中后序遍…...

字节小米等后端岗位C++面试题

C 基础 引用和指针之间的区别?堆栈和堆中的内存分配有何区别?存在哪些类型的智能指针?unique_ptr 是如何实现的?我们如何强制在 unique_ptr 中仅存在一个对象所有者?shared_ptr 如何工作?对象之间如何同步…...

IOS HTTPS代理抓包工具使用教程

打开抓包软件 在设备列表中选择要抓包的 设备,然后选择功能区域中的 HTTPS代理抓包。根据弹出的提示按照配置文件和设置手机代理。如果是本机则会自动配置,只需要按照提醒操作即可。 iOS 抓包准备 通过 USB 将 iOS 设备连接到电脑,设备需解…...

renben-openstack-使用操作

管理员操作 (1)上传一个qcow2格式的centos7镜像 (2)管理员------>云主机类型------>创建云主机类型 名称:Centos7 VCPU数量:1 内存: 1024 根磁盘: 10G 其他的默认 点击创建云主机类型即可 界面会显示如下 创建公网络 (1)创建…...

HOW - Form 表单确认校验两种模式(以 Modal 场景为例)

目录 一、背景二、具体1. 模式一:点击确认进行校验提示2. 模式二:确认按钮依赖于表单内容实现说明 一、背景 基于react、antd form分别实现如下两种模式: 1、一个 Modal,点击确认进行校验提示2、一个 Modal,确认按钮…...

MATLAB算法实战应用案例精讲-【数模应用】图像边缘检测(附MATLAB和python代码实现)(二)

目录 前言 算法原理 相关概念 二值图像、灰度图像、彩色图像 邻接性、连通性 图像滤波 频率 滤波器 边缘检测算子:Sobel算子、Scharr算子、Laplacian算子、Canny算子 梯度计算 + 顶帽 + 黑帽 + 拉普拉斯金字塔 相位一致性(Phase Congruency,PC) 几种常见的算法…...

高考日语听力中常考2大类关键词

高考日语听力中,有些关键词的出现频率很高,同学们掌握这些关键词的读音和意思,可以提高听力答题的正确率,如时间类、地点类、天气类关键词……本文档为大家整理了干货,高考日语听力常考关键词,帮助同学们区分和积累常用词汇,记得要持续关注哦! 时间类关键词 1.星期 ∙…...

windows和linux的抓包方式

1.实验准备: 一台windows主机,一台linux主机 wireshark使用: 打开wireshark,这些有波动的就代表可以有流量经过该网卡,选择一张有流量经过的网卡 可以看到很多的流量,然后可以使用过滤器来过滤想要的流量…...

工业 4G 路由器赋能远程医疗,守护生命线

在医疗领域,尤其是偏远地区的医疗救治场景中,工业 4G 路由器正发挥着无可替代的关键作用,宛如一条坚韧的 “生命线”,为守护患者健康持续赋能。 偏远地区医疗资源相对匮乏,常常面临着专业医生短缺、诊疗设备有限等困境…...

《太阳之子》Build16524106官方中文学习版

《太阳之子》官方中文版https://pan.xunlei.com/s/VODabFuJ5gA7rCUACMulT5YGA1?pwdc47e# 集战术狙击、解谜与轻度潜行要素于一身,呈现独一无二的第三人称射击游戏体验。每关你只有一发子弹,但你可以进行在命中时重新瞄准、绕过障碍物、加速击穿护甲等操…...

shell-条件判断

目录 一、条件判断 1.按照文件类型进行判断 2.按照文件权限进行判断 3.两个文件之间进行比较 4.两个整数之间进行比较 5.字符串的判断 6.多重条件判断 二、if条件判断 1.单分支if条件语句 2.双分支if条件语句 (1)判断某文件是否存在 &#x…...

【TI毫米波雷达】DCA1000不使用mmWave Studio的数据采集方法,以及自动化实时数据采集

【TI毫米波雷达】DCA1000不使用mmWave Studio的数据采集方法,以及自动化实时数据采集 mmWave Studio提供的功能完全够用了 不用去纠结用DCA1000低延迟、无GUI传数据 速度最快又保证算力无非就是就是Linux板自己写驱动做串口和UDP 做雷达产品应用也不会采用DCA1000的…...

20250110_ PyTorch中的张量操作

文章目录 前言1、torch.cat 函数2、索引、维度扩展和张量的广播3、切片操作3.1、 encoded_first_node3.2、probs 4、长难代码分析4.1、selected4.1.1、multinomial(1)工作原理: 总结 前言 1、torch.cat 函数 torch.cat 函数将两个张量拼接起来,具体地是…...

【ROS2】☆ launch之Python

☆重点 ROS1和ROS2其中一个很大区别之一就是launch的编写方式。在ROS1中采用xml格式编写launch,而ROS2保留了XML 格式launch,还另外引入了Python和YAML 编写方式。选择哪种编写取决于每位开发人员的爱好,但是ROS2官方推荐使用Python方式编写…...

unity rb.velocity和transform.position

rb.velocity和transform.position是用来控制物体位置的两种方式,前者通常用来控制人物的移动,它们的主要区别和适用场景如下 一,rb.velocity(控制刚体的速度) 它可以直接控制物体的速度,而不是物体的位置…...

景芯SOC设计实战

终身辅导、一对一辅导,手把手教您完成SoC全流程设计,从入门到进阶,带您掌握SoC芯片架构、算法、设计、验证、DFT、后端及低功耗全流程!直播视频不定期升级!让您快速超越同龄人! 景芯团队主打文档服务器实战…...

【WRF运行报错】总结WRF运行时报错及解决方案(持续更新)

目录 ./real.exe错误1:ERROR while reading namelist physics./wrf.exe错误1:FATAL CALLED FROM FILE: <stdin> LINE: 2419 Warning: too many input landuse types参考./real.exe 错误1:ERROR while reading namelist physics 执行./real.exe时,报错如下: taski…...

Mysql快速列出来所有列信息

文章目录 需求描述实现思路1、如何查表信息2、如何取字段描述信息3、如何将列信息一行展示4、拼接最终结果 需求描述 如何将MySQL数据库中指定表【tb_order】的所有字段都展示出来&#xff0c;以备注中的中文名为列名。 实现思路 最终展示效果&#xff0c;即拼接出可执行执行…...

spring boot发送邮箱,java实现邮箱发送(邮件带附件)3中方式【保姆级教程一,代码直接用】

文章目录 Java发送邮箱的方式1. 基于 Javax.mail 实现关于附件上传的方法 2. 基于 org.apache.commons.mail 实现常见报错 3. 基于 spring-boot-starter-mail 实现&#xff08;推荐&#xff09; 实际开发时需要实现邮件发送&#xff0c;本文章实现如何从零实现邮件发送。也就是…...

数据集-目标检测系列- 电话 测数据集 call_phone >> DataBall

数据集-目标检测系列- 电话 测数据集 call DataBall 助力快速掌握数据集的信息和使用方式&#xff0c;会员享有 百种数据集&#xff0c;持续增加中。 需要更多数据资源和技术解决方案&#xff0c;知识星球&#xff1a; “DataBall - X 数据球(free)” 贵在坚持&#xff01; …...

Zstandard压缩算法

简介 Zstandard(缩写为zstd)是一种开源的无损数据压缩算法,主要设计目标是提供高比率的压缩和快速的解压缩速度。它由Yann Collet开发,并于2015年首次发布。 特点 高比率的压缩(通常比gzip更好)。快速的解压缩速度(通常比gzip更快)。支持流式解压缩。可以选择不同的压…...

npm i 报错

nodejs中 使用npm install命令时报错 npm err! file C: \user\admin\package.json_package.json 里缺少 description 和 repository 两个n字段。-CSDN博客...

【LeetCode】力扣刷题热题100道(26-30题)附源码 轮转数组 乘积 矩阵 螺旋矩阵 旋转图像(C++)

目录 1.轮转数组 2.除自身以外数组的乘积 3.矩阵置零 4.螺旋矩阵 5.旋转图像 1.轮转数组 给定一个整数数组 nums&#xff0c;将数组中的元素向右轮转 k 个位置&#xff0c;其中 k 是非负数。 class Solution { public:void rotate(vector<int>& nums, int k) …...