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

OC底层原理【一】 alloc init new

OC底层原理【一】 alloc init && new

文章目录

  • OC底层原理【一】 alloc init && new
    • 前言
    • alloc
      • slowpath(checkNil && !cls)) 和 fastpath(!cls->ISA()->hasCustomAWZ())
      • !cls->ISA()->hasCustomAWZ())
    • obj->initInstanceIsa();将类与isa关联
    • NSObject的alloc
    • 内存对齐
        • sizeof
        • class_getInstanceSize
        • malloc_size
      • 内存对齐规则
        • 属性重排
      • NSObject 走objc_alloc方法

前言

这里笔者参考阅读的是objc838系列代码,但是由于笔者的Xcode版本不支持运行该版本,所以笔者采用的是运行objc906的代码,然后对照阅读的Objc838。这里感谢这位大佬的博客提供了一个可编译代码:objc906

这里先看一下alloc的一个流程图:

alloc + init 整体源码的探索流程

alloc

首先OC的对象的一个创建是从alloc开始的:

GGObject *obj = [[GGObject alloc] init];

这时候我们逐步跳转alloc函数的每一个步骤,了解函数的一个调用顺序:

+ (id)alloc {return _objc_rootAlloc(self);
}
_objc_rootAlloc(Class cls)
{return callAlloc(cls, false/*checkNil*/, true/*allocWithZone*/);
}
static ALWAYS_INLINE id
callAlloc(Class cls, bool checkNil, bool allocWithZone=false)
{
#if __OBJC2__if (slowpath(checkNil && !cls)) return nil; // 这里大概率为false 所以不会进入nilif (fastpath(!cls->ISA()->hasCustomAWZ())) { //判断一个类是否有自定义的 +allocWithZone 实现,没有则走到if里面的实现return _objc_rootAllocWithZone(cls, nil);}
#endif// No shortcuts available.if (allocWithZone) {return ((id(*)(id, SEL, struct _NSZone *))objc_msgSend)(cls, @selector(allocWithZone:), nil);}return ((id(*)(id, SEL))objc_msgSend)(cls, @selector(alloc));
}
bool hasDefaultAWZ( ) { //fastpath路径return data()->flags & RW_HAS_DEFAULT_AWZ; //这个值会被储存到·metaClass中}
#define RW_HAS_DEFAULT_AWZ    (1<<16)

slowpath(checkNil && !cls)) 和 fastpath(!cls->ISA()->hasCustomAWZ())

//x的值和很可能为真,真值判断
#define fastpath(x) (__builtin_expect(bool(x), 1))
#define slowpath(x) (__builtin_expect(bool(x), 0))
//x的值很可能为假,假值判断

其中的__builtin_expect指令是由gcc引入的, 1、目的:编译器可以对代码进行优化,以减少指令跳转带来的性能下降。即性能优化 2、作用:允许程序员将最有可能执行的分支告诉编译器。 3、指令的写法为:__builtin_expect(EXP, N)。表示 EXP==N的概率很大。 4、fastpath定义中__builtin_expect((x),1)表示 x 的值为真的可能性更大;即 执行if 里面语句的机会更大 5、slowpath定义中的__builtin_expect((x),0)表示 x 的值为假的可能性更大

!cls->ISA()->hasCustomAWZ())

这里是判断这个类别有没有一个 判断一个类是否有自定义的 +allocWithZone 实现

这里大概率是正确的所以会直接跳转到里面的函数:

_objc_rootAllocWithZone(Class cls, malloc_zone_t *zone __unused) //unused 一个 宏定义,它的作用是为 未使用的变量 打上一个标记,让编译器不要对它发出警告。
{// allocWithZone under __OBJC2__ ignores the zone parameterreturn _class_createInstanceFromZone(cls, 0, nil,OBJECT_CONSTRUCT_CALL_BADALLOC);
}

现在才算正式步入正题,进入我们的alloc的一个核心部分代码:

_class_createInstanceFromZone(Class cls, size_t extraBytes, void *zone,int construct_flags = OBJECT_CONSTRUCT_NONE,bool cxxConstruct = true,size_t *outAllocatedSize = nil) // cls->instanceSize:计算需要开辟的内存空间大小calloc:申请内存,返回地址指针 obj->initInstanceIsa:将 类 与 isa 关联
{ASSERT(cls->isRealized()); //断言判断有没有实现// Read class's info bits all at once for performance 一次性读取类的信息来提高性能 bool hasCxxCtor = cxxConstruct && cls->hasCxxCtor(); bool hasCxxDtor = cls->hasCxxDtor();bool fast = cls->canAllocNonpointer(); //是否支持一个快速创建size_t size;size = cls->instanceSize(extraBytes); // 注意大小,extraBytes大小为0if (outAllocatedSize) *outAllocatedSize = size;id obj;if (zone) { //这里是一个分配内存的内容obj = (id)malloc_zone_calloc((malloc_zone_t *)zone, 1, size); //malloc_zone_calloc 是苹果系统(macOS/iOS)特有的底层 API,用于在指定内存分配区域(malloc zone)中分配并初始化零值内存。} else {obj = (id)calloc(1, size); }if (slowpath(!obj)) {if (construct_flags & OBJECT_CONSTRUCT_CALL_BADALLOC) {return _objc_callBadAllocHandler(cls);}return nil;}if (!zone && fast) {//将 cls类 与 obj指针(即isa) 关联obj->initInstanceIsa(cls, hasCxxDtor);} else {// Use raw pointer isa on the assumption that they might be// doing something weird with the zone or RR.obj->initIsa(cls);}if (fastpath(!hasCxxCtor)) {return obj;}construct_flags |= OBJECT_CONSTRUCT_FREE_ONFAILURE;return object_cxxConstructFromClass(obj, cls, construct_flags);
}

这里我们先看一下的一个函数的流程图

_class_createInstanceFromZone流程

我们从这个流程图开始往下看:

inline size_t instanceSize(size_t extraBytes) const {if (fastpath(cache.hasFastInstanceSize(extraBytes))) {return cache.fastInstanceSize(extraBytes); // 这个函数是一个快速计算高度}size_t size = alignedInstanceSize() + extraBytes; // 计算类中所有属性的大小 + 额外的字节数0// CF requires all objects be at least 16 bytes.if (size < 16) size = 16;return size;}

这里我们跳转到fastInstanceSize这个方法中进行一个学习:

size_t fastInstanceSize(size_t extra) const{ASSERT(hasFastInstanceSize(extra));//Gcc的内建函数 __builtin_constant_p 用于判断一个值是否为编译时常数,如果参数EXP 的值是常数,函数返回 1,否则返回 0if (__builtin_constant_p(extra) && extra == 0) {return _flags & FAST_CACHE_ALLOC_MASK16;} else {size_t size = _flags & FAST_CACHE_ALLOC_MASK;// remove the FAST_CACHE_ALLOC_DELTA16 that was added// by setFastInstanceSize// 删除由setFastInstanceSize添加的FAST_CACHE_ALLOC_DELTA16 8个字节return align16(size + extra - FAST_CACHE_ALLOC_DELTA16); // 会将输入值向上舍入(round up)到最近的 16 字节对齐的地址。提高访问效率}}
//16字节内存对齐函数
static inline size_t align16(size_t x) { return (x + size_t(15)) & ~size_t(15);
}

内存字节对齐原则:

  • 数据成员对齐规则:struct 或者 union 的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员大小(只要该成员有子成员,比如数据、结构体等)的整数倍开始(例如int在32位机中是4字节,则要从4的整数倍地址开始存储)
  • 数据成员为结构体:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储(例如:struct a里面存有struct b,b里面有char、int、double等元素,则b应该从8的整数倍开始存储)
  • 结构体的整体对齐规则:结构体的总大小,即sizeof的结果,必须是其内部做大成员的整数倍,不足的要补齐

内存对齐的一个好处:

  • 16字节对齐后,可以加快CPU读取速度,同时使访问更安全,不会产生访问混乱的情况。 主要是因为isa指针占了8个字节,这样可以保证一个对象有一个

  • 通常内存是由一个个字节组成的,cpu在存取数据时,并不是以字节为单位存储,而是以为单位存取,块的大小为内存存取力度。频繁存取字节未对齐的数据,会极大降低cpu的性能,所以可以通过减少存取次数降低cpu的开销

这里我们看一下字节内存对齐函数的操作流程:

16字节对齐算法图解

这里加15的原因是:

  • 确保 x 即使不是 16 的倍数,也能通过“向上舍入”到最近的 16 倍数。

为什么用 & ~15

  • 1111 1111 1111 0000 这里注意的点是他一定会通过15按位与,把后面4位都清0,这里可以类比掩码的处理,保证后四位一定为0,这样两种保证就可以让他肯定是16的某一个整数倍

这种算法保证了一个16位,这样就实现了一个内存对齐的效果

这里我们在calloc这个位置上打上一个断点

image-20250415171741406

这里可以看到我们打印出来的obj,还没有和类别连接起来。按照之前对象的打印逻辑来讲他应该类似于这个<LGPerson: 0x01111111f>

  • 这样说明了objc的地址还没有和穿入的cls进行一个关联
  • 同时印证了alloc的根本作用就是开辟内存

obj->initInstanceIsa();将类与isa关联

现在这一个步骤做的就是将类与地址指针即isa指针进行一个关联,流程图如下:

inline void 
objc_object::initInstanceIsa(Class cls, bool hasCxxDtor)
{ASSERT(!cls->instancesRequireRawIsa());ASSERT(hasCxxDtor == cls->hasCxxDtor());initIsa(cls, true, hasCxxDtor);
}

image-20250415172621082

主要过程就是初始化一个isa指针,并将isa指针指向申请的内存地址,在将指针与cls类进行关联。

在这里插入图片描述

这张图是一个完整的流程图。这里我们注意一个点,就是alloc函数其实已经完成了创建一个对象并且申请了一块不少于16字节的一个内存空间,绑定isa指针的操作。

这里alloc的核心三步是:

obj->instanceSize > calloc > obj->initInstanceIsa

第一步计算需要开辟的内存大小,第二步开辟内存,第三步将cls类和obj指针关联

那么init函数负责做什么呢?

这里我们可以看一下:

GGObject *obj = [GGObject alloc];
GGObject* obj2 = [obj init];
GGObject* obj3 = [obj init];
NSLog(@"%@, %p, %p", obj, obj, &obj);
NSLog(@"%@, %p, %p", obj3, obj3, &obj3);
NSLog(@"%@, %p, %p", obj2, obj2, &obj2);

这里我们看这个部分的代码的输出结果:

image-20250415220917263

这里说明了他们三个是同一个对象,但是他们三个指向同一块内存空间,但是他们申请的一个内存地址有不一样

这里我们认识一下init的源码:

- (id)init {return _objc_rootInit(self);
}
_objc_rootInit(id obj)
{// In practice, it will be hard to rely on this function.// Many classes do not properly chain -init calls.return obj;
}

这里不难看出init没有做什么操作,只是把当前的对象给返回了。这里主要是通过调用init方法作为一个工厂模式,方便开发着自行定义重写。

NSObject的alloc

这里简单给出一张图做一个简单的介绍,说明他和自定义类的一个区别:

NSObject alloc源码流程

自定义类 alloc源码流程

由此可以得出NSObject中的alloc会走到objc_alloc,其实这部分是由系统级别的消息处理逻辑,所以NSObject的初始化是由系统完成的,因此也不会走到alloc的源码工程中.

内存对齐

这里笔者就简单介绍一下有关OC这里的内容一个内存对齐的内容:

NSObject *objc = [[NSObject alloc] init];
NSLog(@"objc对象类型占用的内存大小%lu", sizeof(objc));
NSLog(@"objc对象实际占有的内存大小%lu", class_getInstanceSize([objc class]));
NSLog(@"objc对象实际占有的内存大小%lu", malloc_size((__bridge const void*)(objc)));

这里我们看一下他的一个打印结果:

image-20250418204312415

这里我们简单分析一下这里的一个原因:

sizeof
  • sizeof是一个操作符,并不是一个函数
  • 用siezof计算内存大小的时候,传入的对象是数据类型,这个在编译期的便宜阶段就会确定大小而不是在运行时确定
  • sizeof最后的道德几个是该数据类型占用空间的一个大小
class_getInstanceSize

这里是有runtime提供的一个api,用于获取类的实例对象所占用的一个内存大小.返回一个具体的字节数,本质是获取实力对象中成员变量的一个内存大小

malloc_size

这个反复该是获取系统实际发分配内存的大小

这里为什么会出现一个实际分配了16个字节但是却实际质用占用一个8字节,而且为什么sizeof是返回一个8字节?

  • sizeof:之所以是一个8字节是因为,我么这里对于类似于NSObject定义实例对象而言,对象类型的本质就是一个结构体指针,其实这里的就是指针,所以sizeof打印的其实是一个对象的指针大小我们知道一个指针的内存大小为8,所以打印的是8
  • Class_getInstanceSize:计算对象实际中诺安用的一个内存大小,这个需要根据类的熟悉而变化,
  • malloc_size计算对象实际分配的内存大小,这个由系统完成,可以由系统完成的,可以从上面的打印结果看出,实际分配分配和实际占用的内存大小并不相等.

内存对齐规则

数据类型对应的字节数表格

上面是我们的一个内存对齐的一个规则,我们可以用这个规则来分析下面两个结构体的一个内存大小的一个打印情况:

结构体对应的存储情况

这里就不过多赘述一个计算结构体大小的一个逻辑了,但是从上面我们可以看出来这里的代吗的一个内存上的一个优化了,明明是一样的一个属性内容,但是却有着不同的一个内存大小的情况.

属性重排

如果结构体中的数据成员是根据内存从大到小的顺序定义的吗根据内存对齐规则来计算就诶狗蹄内存大小,我们只需要补齐比较少的一个内存padding就可以满足内存的对齐的一个规则,所以我们可也对类中的属性进行一个重新排序,来达到一个优化内存的目的.

这里我们可以先看这里的一个代吗内容:

@interface CJLPerson : NSObject@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *nickName;
// @property (nonatomic, copy) NSString *hobby;
@property (nonatomic, assign) int age;
@property (nonatomic, assign) long height;@property (nonatomic) char c1;
@property (nonatomic) char c2;
@end@implementation CJLPerson@endCJLPerson *person = [CJLPerson alloc];
person.name      = @"CJL";
person.nickName  = @"C";
person.age       = 18;
person.c1        = 'a';
person.c2        = 'b';
NSLog(@"%@", person);

这时候我们开始有一个断点调试,来观察这个对象中每一个成员变量的数据的时候,我们按照我们之前的一个顺序来看,先找到name和nickname

在这里插入图片描述
在这里插入图片描述

从这两张图片我们可以看出一个内容,就是首先我们这里的一个name和nickName的地址都可以找到这个对象,但是如果我们按照之前的思路来找我们的一个age和height就会发现有问题:

image-20250418215608712

这里变成了一个乱码,这里是因为apple对于这几个属性的内存进行了一个重排,因为age类型炸按5个字节,c1,c2类型站1个字节,通过4+1+!的方式,按照8字节对齐,不足不其方式在统一快内存中.

image-20250418215942594

NSObject 走objc_alloc方法

这里我们现在先认识一下NSObject的objc_alloc方法,他和我们之前讲的alloc方法不一致

  • NSObject 是iOS中的基类,所有自定义的累都要继承自NSObject
  • LGPerson是继承于NSObject累的,重写了alloc方法。

为什么NSobject调用alloc方法,会走到objc_alloc源码

而LGPerson中的alloc会走两次?即调用了alloc,进入源码,还要走到objc_alloc

这里的原因其实是因为NSObject

相关文章:

OC底层原理【一】 alloc init new

OC底层原理【一】 alloc init && new 文章目录 OC底层原理【一】 alloc init && new前言allocslowpath(checkNil && !cls)) 和 fastpath(!cls->ISA()->hasCustomAWZ())!cls->ISA()->hasCustomAWZ()) obj->initInstanceIsa();将类与isa关…...

集合框架拓展--stream流的使用

Stream&#xff08;JDK8新特性&#xff09; 什么是Stream&#xff1f; 也叫stream流&#xff0c;是JDK8开始新增的一套API&#xff08;java.util.stream.*&#xff09;,可以用于操作集合或数组中的数据 优势&#xff1a;Stream流大量地结合了Lambda的语法风格来编程&#xff…...

Beszel​​ 轻量级服务器监控平台的详细安装步骤

什么是 Beszel Beszel 是一个轻量级的服务器监控平台&#xff0c;包含 Docker 统计信息、历史数据和警报功能。 它拥有友好的 Web 界面、简单的配置&#xff0c;并且开箱即用。它支持自动备份、多用户、OAuth 身份验证和 API 访问 https://beszel.dev/zh/guide/what-is-besz…...

Spring 微服务解决了单体架构的哪些痛点?

1. 部署困难 (Deployment Difficulty & Risk) 单体痛点: 整体部署: 对单体应用的任何微小修改&#xff08;哪怕只是一行代码&#xff09;&#xff0c;都需要重新构建、测试和部署整个庞大的应用程序。部署频率低: 由于部署过程复杂且风险高&#xff0c;发布周期通常很长&a…...

Kotlin delay方法解析

本文记录了kotlin协程(Android)中delay方法的字节码实现&#xff0c;并解析了delay方法如何实现挂起操作。 一、delay方法介绍 1.1、delay方法使用举例 class TestDelay {suspend fun testDelay() {Log.d("TestDelay", "before delay")delay(1000)Log.d…...

C# 类型、存储和变量(用户定义类型)

本章内容 C#程序是一组类型声明 类型是一种模板 实例化类型 数据成员和函数成员 预定义类型 用户定义类型 栈和堆 值类型和引用类型 变量 静态类型和dynamic关键字 可空类型 用户定义类型 除了C#提供的16种预定义类型&#xff0c;还可以创建自己的用户定义类型。有6种类型可以…...

C语言之高校学生信息快速查询系统的实现

&#x1f31f; 嗨&#xff0c;我是LucianaiB&#xff01; &#x1f30d; 总有人间一两风&#xff0c;填我十万八千梦。 &#x1f680; 路漫漫其修远兮&#xff0c;吾将上下而求索。 C语言之高校学生信息快速查询系统的实现 目录 任务陈述与分析 问题陈述问题分析 数据结构设…...

Windows串口通信

Windows串口通信相比较Android串口通信,在开发上面相对方便一些。原理都是一样,需要仔细阅读厂商设备的串口通信协议。结合串口调试助手进行测试,测试通过后,编写代码实现。 比如近期就接触到了一款天平,其最大测量值为100g,测量精度0.001g。 拿到手之后我就先阅读串口通…...

从零开始用Pytorch实现LLaMA 4的混合专家(MoE)模型

近期发布的LLaMA 4模型引入了混合专家&#xff08;Mixture of Experts, MoE&#xff09;架构&#xff0c;旨在提升模型效率和性能。尽管社区对LLaMA 4的实际表现存在一些讨论&#xff0c;但MoE作为一种重要的模型设计范式&#xff0c;继Mistral等模型之后再次受到关注。 所以我…...

python3GUI--仿网课答题播放器 By:PyQt5(分享)

文章目录 一&#xff0e;前言二&#xff0e;相关知识1.PyQt52.QMediaPlayer3.QThread4.Sqlite3 二&#xff0e;展示1.主界面2.课程播放&问答3.字幕调整4.播放列表折叠5.添加课程 三&#xff0e;心得与分享1.数据本地化2.自定义组件3.系统流程图与代码量4.免责声明 四&#…...

Python基础总结(八)之循环语句

文章目录 一、for循环1.1 for循环格式1.2 for ...else1.3 for...break1.4 for...continue 二、while循环2.1 while循环格式2.2 while...break2.3 while...continue2.4 while ...else 循环语句就如其名&#xff0c;就是重复的执行一段代码&#xff0c;直到满足退出条件时&#x…...

21. git apply

基本概述 git apply 的作用是&#xff1a;应用补丁文件 基本用法 1.命令格式 git apply [选项] <补丁文件>2.应用补丁 git apply patchfile.patch将补丁应用到工作目录&#xff0c;但不会自动添加到暂存区&#xff08;需手动 git add&#xff09; 常用选项 1.检查…...

第一章:MySQL视图基础

1. 视图是什么&#xff1f; ​​定义​​&#xff1a;视图&#xff08;View&#xff09;是一种虚拟表&#xff0c;其内容基于一个或多个真实表&#xff08;基表&#xff09;的查询结果。视图不实际存储数据&#xff0c;而是通过查询动态生成数据。​​核心特点​​&#xff1a…...

深入理解基线检查:网络安全的基石

深入理解基线检查&#xff1a;网络安全的基石 一、引言 在信息技术飞速发展的今天&#xff0c;网络安全已成为企业和组织正常运营的关键保障。从日常办公系统到关键业务应用&#xff0c;任何环节的安全漏洞都可能导致严重的后果&#xff0c;如数据泄露、系统瘫痪等。基线检查作…...

33-公交车司机管理系统

技术&#xff1a; 基于 B/S 架构 SpringBootMySQLvueelementui 环境&#xff1a; Idea mysql maven jdk1.8 node 用户端功能 1.首页:展示车辆信息及车辆位置和线路信息 2.模块:车辆信息及车辆位置和线路信息 3.公告、论坛 4.在线留言 5.个人中心:修改个人信息 司机端功能…...

【AI实践】使用DeepSeek+CherryStudio绘制Mermaid格式图表

目录 工具准备创建DeepSeek API Key安装CherryStudioMermaid在线编辑器 绘制图表编写提示词在CherryStudio中调用DeepSeek复制源码到Mermaid编辑器中进行微调 图表示例流程图思维导图甘特图 工具准备 创建DeepSeek API Key 打开DeepSeek开放平台&#xff0c; 注册并充值成功后…...

TCP报文段解析:从抽象到具象的趣味学习框架

TCP报文段解析&#xff1a;从抽象到具象的趣味学习框架 一、What&#xff1a;TCP报文段长什么样&#xff1f; 核心结构&#xff08;类比快递包裹&#xff09;&#xff1a; 复制 下载 | 源端口&#xff08;16位&#xff09;| 目的端口&#xff08;16位&#xff09;| |-----…...

B+树节点与插入操作

B树节点与插入操作 设计B树节点 在设计B树的数据结构时&#xff0c;我们首先需要定义节点的格式&#xff0c;这将帮助我们理解如何进行插入、删除以及分裂和合并操作。以下是对B树节点设计的详细说明。 节点格式概述 所有的B树节点大小相同&#xff0c;这是为了后续使用自由…...

rollup使用讲解

rollup 总结 什么是 rollup? rollup 是一个 JavaScript 模块打包器,在功能上要完成的事和 webpack 性质一样,就是将小块代码编译成大块复杂的代码,例如 library 或应用程序。在平时开发应用程序时,我们基本上选择用 webpack,相比之下,rollup.js 更多是用于 library 打…...

高边开关和低边开关的区别

高边驱动和低边驱动的区别 在高边驱动和低边驱动中&#xff0c;开关的位置直接影响电路在负载短路时的安全性和电流路径。以下是关键原理的分步解释&#xff1a; 1. 高低边驱动的结构对比 高边驱动&#xff08;High-Side Drive&#xff09; 电路结构&#xff1a; 电源正极 →…...

PG psql --single-transaction 参数功能

文章目录 PG psql --single-transaction 参数功能 PG psql --single-transaction 参数功能 test.sql 文件 create table test1(id int); CREATE OR REPLACE FUNCTION func_test() RETURNS INTEGER AS $BODY$ BEGINxxxreturn 0; END; $BODY$ LANGUAGE plpgsql VOLATILE CALLE…...

C++ 多态

1.多态的概念 多态&#xff08;polymorphism&#xff09;通俗来说就是多种形态。多态分为编译时多态&#xff08;静态多态&#xff09;和运行时多态&#xff08;动态多态&#xff09;&#xff0c;这里我们重点是运行时多态&#xff0c;编译时多态主要就是我们前面的函数重载和…...

【matlab|python】矢量棍棒图应用场景和代码

【matlab|python】矢量棍棒图应用场景和代码 矢量棍棒图的介绍和作用 矢量棍棒图&#xff08;stick plot&#xff09;是一种用于可视化 方向性时间序列数据 的图形工具。它常用于大气科学和海洋科学中&#xff0c;以直观地展示 风场、海流 或 其他矢量变量 随时间的变化情况。 …...

Matlab 五相电机仿真

1、内容简介 Matlab 208-五相电机仿真 可以交流、咨询、答疑 2、内容说明 略 3、仿真分析 略 4、参考论文 略...

计算机视觉cv2入门之视频处理

在我们进行计算机视觉任务时&#xff0c;经常会对视频中的图像进行操作&#xff0c;这里我来给大家分享一下&#xff0c;如何cv2中视频文件的操作方法。这里我们主要介绍cv2.VideoCapture函数的基本使用方法。 cv2.VideoCapture函数...

力扣每日一题781题解-算法:贪心,数学公式 - 数据结构:哈希

https://leetcode.cn/problems/rabbits-in-forest/description/?envTypedaily-question&envId2025-04-20 781.推测兔子数 算法&#xff1a;贪心&#xff0c;数学公式 数据结构&#xff1a;哈希 用哈希存每个兔子报告的同色数量&#xff0c;作为key&#xff0c;同个key…...

MAC-QueryWrapper中用的exists,是不是用join效果更好

在使用MyBatis-Plus的QueryWrapper中的exists方法时,是否改为使用join效果会更好,以及如何 修改。这涉及到SQL优化和MyBatis-Plus的用法。 首先,需要理解exists和join在SQL中的区别。exists用于检查子查询是否返回结果,而join则是将 两个表连接起来,根据某些条件合并行…...

使用 Visual Studio 2022 中的 .http 文件

转自微软技术文档&#xff1a; https://learn.microsoft.com/zh-cn/aspnet/core/test/http-files?viewaspnetcore-9.0 Visual Studio 2022.http 文件编辑器提供了一种便捷的方式来测试 ASP.NET Core项目&#xff0c;尤其是 API 应用。 编辑器提供一个 UI&#xff0c;用于&am…...

相得益彰 — 基于 GraphRAG 事理图谱驱动的实时金融行情新闻资讯洞察

*本文为亚马逊云科技博客文章&#xff0c;仅用于技术分享&#xff0c;不构成投资建议或金融决策支持。文中涉及的公司名称仅用于技术示例&#xff0c;不代表亚马逊云科技观点或与这些公司的商业合作关系。 背景介绍 在当今这个信息爆炸的时代&#xff0c;金融市场每天都在产生…...

为什么this与super不能出现在同一构造器的原因

在 Java 中&#xff0c;this() 和 super() 不能同时出现在同一个构造器中&#xff0c;因为它们都必须作为构造器的第一条语句&#xff0c;而一个构造器的第一条语句只能有一个。以下是详细解释和示例&#xff1a; ⚠️ 核心规则 只能二选一&#xff1a; 每个构造器的第一条语句…...

Linux:网络基础

hello&#xff0c;各位小伙伴&#xff0c;本篇文章跟大家一起学习《Linux&#xff1a;网络基础》&#xff0c;感谢大家对我上一篇的支持&#xff0c;如有什么问题&#xff0c;还请多多指教 &#xff01; 如果本篇文章对你有帮助&#xff0c;还请各位点点赞&#xff01;&#xf…...

C++入门篇(下)

目录 1、引用 1.1 引用概念 1.2 引用特性 1.3 常引用 1.4 使用场景 1.4.1 引用做参数 1.4.2 引用做返回值 1.5 引用和指针的区别 2、内联函数 2.1 概念 2.2 特性 3、auto关键字 4、基于范围的for循环 5、指针空值nullptr 5.1 C98 中的指针空值处理 5.2 C11 …...

QCustomPlot中自定义QCPAbstractPlottable绘图元素

QCPAbstractPlottable 是 QCustomPlot 中所有可绘制图形(如曲线、柱状图等)的基类。要创建自定义的绘图元素&#xff0c;通常需要继承这个类并实现其纯虚函数。 基本步骤 继承 QCPAbstractPlottable 实现必要的纯虚函数 添加自定义属性和方法 注册到 QCustomPlot 系统 完…...

【Bluedroid】蓝牙 HID 设备信息加载与注册机制及配置缓存系统源码解析

本篇解析Android蓝牙子系统加载配对HID设备的核心流程&#xff0c;通过btif_storage_load_bonded_hid_info实现从NVRAM读取设备属性、验证绑定状态、构造描述符并注册到BTA_HH模块。重点剖析基于ConfigCache的三层存储架构&#xff08;全局配置/持久设备/临时设备&#xff09;&…...

【计算机视觉】CV实战项目 - PCC-Net 人群计数

PCC-Net 人群计数项目 项目特点项目运行方式与步骤1. 环境准备2. 数据准备3. 模型训练4. 实验结果 常见问题及解决方法 PCC-Net&#xff08;Perspective Crowd Counting via Spatial Convolutional Network&#xff09;是一个用于人群计数的深度学习项目&#xff0c;旨在通过空…...

Towards Transferable Targeted 3D Adversarial Attack in the Physical World--阅读笔记

目录 简介&#xff1a; 背景&#xff1a; 挑战&#xff1a; 目的&#xff1a; 技术细节&#xff1a; 贡献&#xff1a; ​​1. NeRF的核心作用&#xff1a;3D重建与参数化表示​​ ​​2. 对抗优化的创新&#xff1a;NeRF参数空间的双优化​​ ​​2.1 传统方法的局限…...

​opencv图像库编程

一、下载安装 opencv 1.1 下载安装包 1.2 解压缩 unzip opencv-3.4.11.zip 解压缩以后主目录文件夹如下&#xff1a; 1.3 进入到解压后的文件夹中 cd opencv-3.4.11 二、使用 cmake安装opencv 2.1 进入 root 用户&#xff0c;并更新一下 sudo su sudo apt-get update …...

星拍相机APP:时尚与科技的完美融合,打造你的专属美

在数字时代&#xff0c;手机相机不仅是记录生活的工具&#xff0c;更是表达个性和创意的平台。今天&#xff0c;我们要介绍的 星拍相机APP&#xff0c;就是这样一款匠心制作的手机相机应用。它融合了时尚与科技&#xff0c;提供了多样化的魔法美颜功能&#xff0c;让每一次拍摄…...

puzzle(0531)脑力航迹

目录 脑力航迹 规则 解法 简单模式 中等模式 困难模式 专家模式 脑力航迹 规则 2条航迹会产生一个相对航迹&#xff1a; 根据相对航迹和其中一个航迹推导另外一个航迹。 解法 没有任何需要推理的地方&#xff0c;就是纯粹的2个矢量相加。 简单模式 中等模式 困难模…...

【英语语法】词法---形容词

目录 形容词1. 形容词的核心功能2. 形容词的位置(1) 前置定语&#xff08;最常见&#xff09;(2) 后置定语&#xff08;特殊情况&#xff09;(3) 表语位置&#xff08;系动词后&#xff09; 3. 形容词的比较级与最高级(1) 规则变化(2) 不规则变化(3) 用法对比 4. 多个形容词修饰…...

理解 React 的 useEffect

文章目录 React 的 useEffect一、什么是副作用&#xff08;Side Effects&#xff09;&#xff1f;二、useEffect 的基本用法三、依赖数组的三种情况1. 无依赖数组&#xff08;每次渲染后都执行, 不推荐&#xff09;2. 空依赖数组&#xff08;仅在挂载时执行一次&#xff09;3. …...

2.1 基于委托的异步编程方法

基于委托的异步编程模型是 .NET 早期版本中实现异步操作的一种方式,主要通过 BeginInvoke 和 EndInvoke 方法来实现。这种基于委托的异步模式已被 Task 和 async/await 模式取代,但在维护旧代码时仍可能遇到这种模式。 委托的方法中:Invoke用于同步调用; 而BeginInvoke与E…...

对于在线教育或知识付费类网站视频处理方案

一、视频格式&#xff1a; 1. 推荐格式&#xff1a;HLS&#xff08;HTTP Live Streaming&#xff09; 优势‌&#xff1a; ‌自适应码率‌&#xff1a;根据用户网络状况自动切换清晰度&#xff0c;避免卡顿。‌广泛兼容性‌&#xff1a;iOS/macOS 原生支持&#xff0c;Android…...

Gen - CDPT举例说明:动态上下文前缀(输入先和标签结合,输出结果会更贴近标签内容)

Gen - CDPT举例说明:动态上下文前缀(输入先和标签结合,输出结果会更贴近标签内容) 目录 Gen - CDPT举例说明:动态上下文前缀(输入先和标签结合,输出结果会更贴近标签内容)输入文本示例Gen - CDPT模型处理过程示例什么是:提示次优动态前缀提示方法生成与这条评论上下文…...

UCSC CTF 2025|MISC

1、USB flag{ebdfea9b-3469-41c7-9070-d7833ecc6102} 2、three part1是图片隐水印 part1&#xff1a;8f02d3e7 part2是2进制变换 -ce89-4d6b-830e- Part3先从pass.pcapng得到密码字典 解压缩密码&#xff1a;thinkbell 3个部分合并得到flag{8f02d3e7-ce89-4d6b-830e-5d0cb5…...

FTP客户端实现(文件传输)

文章目录 &#x1f9f1; 一、FTP 基础架构回顾&#x1f680; 二、FTP 客户端的核心结构&#x1f517; 三、连接与登录过程&#x1f4cc; 1. ftp_create()&#x1f4cc; 2. ftp_connect()&#x1f4cc; 3. ftp_login() &#x1f4c1; 四、上传文件实现&#xff08;ftp_upload_fi…...

状态管理最佳实践:Bloc架构实践

状态管理最佳实践&#xff1a;Bloc架构实践 引言 Bloc (Business Logic Component) 是Flutter中一种强大的状态管理解决方案&#xff0c;它基于响应式编程思想&#xff0c;通过分离业务逻辑和UI表现层来实现清晰的代码架构。本文将深入探讨Bloc的核心概念、实现原理和最佳实践…...

嵌入式人工智能应用-第三章 opencv操作 5 二值化、图像缩放

嵌入式人工智能应用 嵌入式人工智能应用-第三章 opencv操作 5 二值化 嵌入式人工智能应用1 二值化1.1 概念介绍1.2 函数介绍1.2 基本应用1.3 参考案例 2 图像缩放2.1 基本概念2.2 函数介绍2.3 基本参考代码2.4 pyrUp 和 pyrDown 函数2.5 函数介绍2.6 参考代码2.7 总结 1 二值化…...

[OS_7] 访问操作系统对象 | offset | FHS | Handle

实验代码可以看去年暑假的这篇文章&#xff1a;【Linux】进程间通信&#xff1a;详解 VSCode使用 | 匿名管道 我们已经知道&#xff0c;进程从 execve 后的初始状态开始&#xff0c;可以通过 mmap 改变自己的地址空间&#xff0c;通过 fork 创建新的进程&#xff0c;再通过 exe…...

【Vulkan 入门系列】创建帧缓冲、命令池、命令缓存,和获取图片(六)

这一节主要介绍创建帧缓冲&#xff08;Framebuffer&#xff09;&#xff0c;创建命令池&#xff0c;创建命令缓存&#xff0c;和从文件加载 PNG 图像数据&#xff0c;解码为 RGBA 格式&#xff0c;并将像素数据暂存到 Vulkan 的 暂存缓冲区中。 一、创建帧缓冲 createFramebu…...