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

【iOS】OC高级编程 iOS多线程与内存管理阅读笔记——自动引用计数(二)

自动引用计数

  • 前言
  • ARC规则
    • 所有权修饰符
      • **__strong修饰符**
      • __weak修饰符
      • __unsafe_unretained修饰符
      • __autoreleasing修饰符
    • 规则
    • 属性
    • 数组

前言

上一篇我们主要学习了一些引用计数方法的内部实现,现在我们学习ARC规则。


ARC规则

所有权修饰符

OC中,为了处理对象,可以将变类型定义为id类型或各种对象类型。

对象类型: 即OC类的指针,例如“NSObject* ”
id类型: 用于隐藏对象类型的类名部分,相当于C语言中的(void *)

ARC有效时,id类型和对象类型同C语言其他类型不同,必须附加上所有权修饰符

  • __strong修饰符
  • __weak修饰符
  • __unsafe_unretained修饰符
  • __autoreleasing修饰符

__strong修饰符

__strong修饰符是id类型和对象类型默认的所有权修饰符。也就是说

id obj = [[NSObject alloc] init];id __strong obj = [[NSObject alloc] init];

这两种代码是一样的。

但是,当ARC无效时,该如何实现__strong修饰符呢。

{id obj = [[NSObject alloc] init];[obj release]
}

如上述代码所示,附有__strong修饰符的变量obj在超出其变量作用域时,即在该变量被废弃时,会释放其被赋予的对象。

因此,我们可以通过在最后调用release代码,实现这一功能。

如“strong”所示,__strong修饰符表示对对象的“强引用”。持有强引用的变量在超出其作用域时废弃。随着强引用的失效,引用的对象会随之释放。

对于自己生成并持有对象的源代码来说,对象的所有者和对象的生存周期都是明确的,那么如果是取得非自己生成并持有的对象呢。

{id__strong obj = [NSMutableArray array];
}

这里我们通过NSMutableArray类的array类方法学习。

{//取得非自己生成并持有的对象id __strong obj = [NSMutableArray array];//变量obj为强引用,所以自己持有对象。
}
//变量obj超出其作用于,强引用失效,自动释放自己持有的对象。

可见取得非自己生成但是持有的对象的生存周期也是明确的

即使是OC类成员变量,也可以在方法参数上,使用附有__strong修饰符的变量。

@interface Test : NSObject
{id __strong obj_;
}
- (void)setObject:(id __strong)obj;
@end@implementation Test
- (id)init
{self = [super init];return self;
}
- (void)setObject:(id __strong)obj
{obj_ = obj;
}
@end

下面我们进行使用:

{id __strong test = [[Test alloc] init];//test持有Test对象的强引用[test setObject:[[NSObject alloc] init];//Test对象的obj_成员,持用NSObjcet对象的强引用。
}
/*因为test变量超出其作用域,强引用失效所以自动释放Test对象。Test对象的所有者不存在,因此废弃该对象。废弃Test对象的同时,Test对象的obj_成员也被废弃,NSObjcet对象的强引用失效自动释放NSObjcet对象所有者不存在,废弃该对象。*/

通过这种方法,无需额外工作便可以使用于类成员变量以及方法参数中。

修饰符可以保证将附有这些修饰符的自动变量初始化为nil。

id __strong ojb0;
//这两种初始化方式相同
id __strong obj0 == nil;

通过__strong修饰符,不必再次键入retain或者release即可实现OC内存管理的思考方式。

并且,id类型和对象类型的所有权修饰符默认为__strong修饰符,所以不需要写上"__strong"。这一设定使得ARC有效以及简单的编程遵循了OC内存管理的思考方式。

__weak修饰符

如果仅使用__strong修饰符,容易发生循环引用的问题,这对项目是毁灭性的。
如以下这种情况:

{id test0 = [[Test alloc] init];//test0持有Test对象A的强引用id test1 = [[Test alloc] init];//test1持有Test对象B的强引用[test0 setObject:test1];/*Test对象A的obj_成员变量持用Test对象B的引用此时,持有Test对象B的强引用的变量为Test对象A的obj_和test1。*/[test1 setObject:test0];/*Test对象B的obj_成员变量持用Test对象A的引用此时,持有Test对象A的强引用的变量为Test对象B的obj_和test0。*/
}/*
因为 test0 变量超出其作用域,强引用失效,
所以自动释放 Test 对象 A。
因为 test1 变量超出其作用域,强引用失效,
所以自动释放 Test 对象 B。
此时,持有 Test 对象 A 的强引用的变量为
Test 对象 B 的 obj_。
此时,持有 Test 对象 B 的强引用的变量为
Test 对象 A 的 obj_。
发生内存泄漏!
*/

如下图所示:
请添加图片描述
循环引用容易发生内存泄漏:即应当废弃的对象在超出其生存周期后继续存在。
上述代码分别将对象A赋给test0,对象B赋给test1后,在超出作用域后无法正确被释放。

为了避免以上这种情况,我们可以采用__weak修饰符。

__weak修饰符:提供弱引用,不能持有对象实例。

id __weak obj = [[NSObject alloc] init];

会出现以下警告。
请添加图片描述

变量 obj 持有对持有对象的弱引用。因此,为了不以自己持有的状态来保存自己生成并持有的对象,生成的对象会立即被释放。

如果使用以下代码,将对象赋值给附有__strong修饰符的变量之后,在赋值附有__weak修饰符的变量,就不会发生警告。

{//自己生成并且持有对象id __strong obj0 = [[NSObject alloc] init];//obj0变量为强引用,所以自己持有对象id __weak obj1 = obj2;//obj1变量持有生成对象的弱引用
}
//因为obj0变量超出其作用域,强引用失效,所以自动释放自己持有的对象
//因为对象的所有者不在,所以会自动废弃obj1

因此上述代码只需要将可能发生循环引用的类成员变量改成附有__weak修饰符的成员变量,即可避免循环引用的问题。如下修:

@interface Test : NSObject
{id __weak obj_;
}
- (void)setObject:(id __strong)obj;
@end

此时对象引用情况如图所示:
请添加图片描述
__weak修饰符还有另一优点:在持有某对象的弱引用时,若该对象被废弃,则此弱引用将自动失效切处于nil被赋值的状态(空弱引用)。

id __weak obj1 = nil;{id __strong obj0 = [[NSObject alloc] init];obj1 = obj0;NSLog(@"A: %@", obj1);}/*obj0变量超出其作用域,强引用失效所以自动释放自己持有的对象因为对象无持用者,所以废弃该对象废弃对象的同时持有该对象弱引用的obj1变量的弱引用失效,nil赋值给obj1*/
NSLog(@"B: %@", obj1);

源代码的结果如下:
请添加图片描述
像这样,使用__weak修饰符即可避免循环引用。通过检查附有__weak修饰符的变量是否为nil,可以判断被赋值的对象是否已废弃。

__unsafe_unretained修饰符

__unsafe_unretained修饰符正如其名,是不安全的所有权修饰符。
附有该修饰符的变量不属于编译器的内存管理对象。
与附有__weak修饰符的变量一样,因此自己生成并持有的对象不能继续为自己所有,所以生成的对象会立即释放。但是当废弃时并不会自动置nil。

id __unsafe_unretained obj1 = nil;{id __strong obj0 = [[NSObject alloc] init];obj1 = obj0;NSLog(@"A: %@", obj1);}
NSLog(@"B: %@", obj1);

以上代码偶尔会运行成功,但更多情况下访问一个空对象会报错。

__autoreleasing修饰符

在 ARC 有效时,用 @autoreleasepool 块替代 NSAutoreleasePool 类,用附有 __autoreleasing 修饰符的变量替代 autorelease 方法

/* ARC无效 */
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
id obj = [[NSObject alloc] init];
[obj autorelease];
[pool drain];/*  有效 */
@autoreleasepool {id __autoreleasing obj = [[NSObject alloc] init];
}

请添加图片描述
但是,通常情况下我们不会显示的附加__autoreleasing修饰符和__strong修饰符。

当使用alloc/new/copy/mutableCopy以外的方法来取得丢下时,该对象会自动被注册到autorelease方法中。

访问附有__weak修饰符的变量时,必须访问注册到autoreleasepool的对象。这是因为__weak修饰符纸持有对象的弱引用,而对象有可能被废弃,但是如果把要访问的对象注册到autoreleasepool中,在@autoreleasepool块结束之前都能确保该对象存在。因此:
使用附有__weak修饰符的变量时必定要使用注册到autoreleasepool中的对象

当我们显示的制定__autoreleasing修饰符时,必须注意对象变量要为自动变量(包括局部变量,函数以及方法参数)

无论 ARC 是否有效,调试用的非公开函数 _objc_autoreleasePoolPrint()都可使用。

该函数可以用于打印当前自动释放池中的所有对象信息。

规则

当ARC有效时,需要遵守的规则:

  • 不能使用 retain/release/retainCount/autorelease
  • 不能使用 NSAllocateObject/NSDeallocateObject
  • 须遵守内存管理的方法命名规则
  • 不要显式调用 dealloc
  • 使用 @autoreleasepool 块替代 NSAutoreleasePool
  • 不能使用区域(NSZone
  • 对象型变量不能作为 C 语言结构体(struct/union)的成员
  • 显式转换 “id” 和 “void *

不能使用 retain/release/retainCount/autorelease

内存管理是编译器的工作,因此没必要使用内存管理的方法。

设置ARC有效时,无需(禁止)再次键入retain或release代码。

实际上,再次键入retain和release代码时会报错,所以应该是禁止键入。
同样的,retainCount和release也会引起编译错误。

不能使用 NSAllocateObject/NSDeallocateObject

在ARC有效时,禁止使用NSAllocateObject函数。同retain方法一样,会引起编译报错。同一释放对象的NSDeallocateObject函数也不可使用。

须遵守内存管理的方法命名规则
当ARC无效时,用于对象生成/持有的方法必须遵守以下的命名规则。

使用alloc/new/copy/mutableCopy时,必须返回给调用方所应当持有的对象。

但是当ARC有效时,init开始的方法必须是实例方法,并且要返回对象。返回的对象应为id类型或该方法声明类的对象类型,或者是该类型的父类或者子类。该返回对象并不注册到autoreleasepool上。基本知识对alloc方法返回值的对象进行初始化处理并返回该对象。如下所示:

-(void) initWithObject:(id) obj;

对象型变量不能作为 C 语言结构体(struct/union)的成员

struct Data {NSMutableArray *array;
};

以上代码会报错

显式转换 “id” 和 “void *

//id和void*互转时需要通过__bridge转换id obj = [[NSObject alloc] init];void *p = (__bridge void *)obj;id o = (__bridge id)p;

__bridge_retained 转换可使要转换赋值的变量也持有所赋值的对象。

/* ARC无效 */
id obj = [[NSObject alloc] init];
void *p = obj;
[(id)p retain];

__bridge_retained 转换变为了 retain。变量 obj 和变量 p 同时持有对象。

void *p = 0;
{id obj = [[NSObject alloc] init];p = (__bridge_retained void *)obj;
}
NSLog(@"class=%@", [(__bridge id)p class]);

变量作用域结束时,虽然随着持有强引用的变量 obj 失效,对象随之释放,但由于 __bridge_retained 转换使变量 p 看上去处于持有该对象的状态,因此该对象不会被废弃。

__bridge_transfer 转换提供与此相反的动作,被转换的变量所持有的对象在该变量被赋值给转换目标变量后随之释放。

id obj = (__bridge_transfer id)p;
//上述代码在ARC无效时如下表达:
/* ARC无效 */
id obj = (id)p;
[obj retain];
[(id)p release];

同 __bridge_retained 转换与 retain 类似,__bridge_transfer 转换与 release 相似。在给 id obj 赋值时 retain 即相当于 __strong 修饰符的变量。

属性

当ARC有效时,以下可作为这种属性声明中使用的属性来用

请添加图片描述
以上各种属性赋值给指定的属性中就相当于赋值给附加各属性对应的所有权修饰符的变量中。

只有 copy 属性不是简单的赋值,它赋值的是通过 NSCopying 接口的 copyWithZone: 方法复制赋值源所生成的对象。

另外,在声明类成员变量时,如果同属性声明中的属性不一致则会引起编译错误。比如下面这种情况。

id obj;//默认为__strong@property (nonatomic, weak) id obj;
//会出现报错//需要改成以下形式
id __weak obj;

数组

使用修饰符赋值数组的使用与变量相同。

id objs[10];id __weak objs[10];

__unsafe_unretained 修饰符以外的 __strong/__weak/__autoreleasing 修饰符保证其指定的变量初始化为 nil。同样地,附有 __strong/__weak/__autoreleasing 修饰符变量的数组也保证其初始化为 nil
下面我们就来看看数组中使用附有 __strong 修饰符变量的例子。

{id objs[2];objs[0] = [[NSObject alloc] init];objs[1] = [NSMutableArray array];
}

数组超出其变量作用域时,数组中各个附有 __strong 修饰符的变量也随之失效,其强引用消失,所赋值的对象也随之释放。这与不使用数组的情形完全一样。

将附有 __strong 修饰符的变量作为动态数组来使用时又如何呢?在这种情况下,根据不同的目的选择使用 NSMutableArrayNSMutableDictionaryNSMutableSet 等 Foundation 框架的容器。这些容器会恰当地持有追加的对象并为我们管理这些对象。

像这样使用容器虽然更为合适,但在 C 语言的动态数组中也可以使用附有 __strong 修饰符的变量,只是必须要遵守一些事项。以下按顺序说明。

声明动态数组用指针。

id __strong *array = nil;

声明动态数组时,我们需要显式的指定为__strong修饰符。

id __strong *array = nil;

由于 “id * 类型” 默认 为 “id __autoreleasing * 类型”,所以有必要显式指定为 strong 修饰符。另外,虽然保证了附有 __strong 修饰符的 id 型变量被初始化为 nil,但并不保证附有 __strong 修饰符的 id 指针型变量被初始化为 nil

使用类名如下述描述:

NSObject * __strong *array = nil;

其次,使用 calloc 函数确保想分配的附有 __strong 修饰符变量的容量占有的内存块。

array = (id __strong *)calloc(entries, sizeof(id));

该源代码分配了 entries 个所需的内存块。由于使用附有 __strong 修饰符的变量前必须先将其初始化为 nil,所以这里使用使分配区域初始化为 0 的 calloc 函数来分配内存。不使用 calloc 函数,在用 malloc 函数分配内存后可用 memset 等函数将内存填充为 0。

但是,像下面的源代码这样,将 nil 代入到 malloc 函数所分配的数组各元素中来初始化是非常危险的。

array = (id __strong *)malloc(sizeof(id) * entries);
for (NSUInteger i = 0; i < entries; ++i)array[i] = nil;

这是因为由 malloc 函数分配的内存区域没有被初始化为 0,因此 nil 会被赋值给附有 __strong 修饰符的并被赋值了随机地址的变量中,从而释放一个不存在的对象。在分配内存时推荐使用 calloc 函数。

像这样,通过 calloc 函数分配的动态数组就能完全像静态数组一样使用。

array[0] = [[NSObject alloc] init];

但是,在动态数组中操作附有 __strong 修饰符的变量与静态数组有很大差异,需要自己释放所有的元素。

当我们要废弃数组时,不能如下直接free。会使数组各元素的值的对象无法释放,引起内存泄漏。如下述代码所示。

free(array);

这是因为:在静态数组中,编译器能够根据变量的作用域自动插入释放赋值对象的代码,而在动态数组中,编译器不能确定数组的生存周期,所以无从处理

如以下源代码所示,一定要将 nil 赋值给所有元素中,使得元素所赋值对象的强引用失效,从而释放那些对象。在此之后,使用 free 函数废弃内存块。

for (NSUInteger i = 0; i < entries; ++i)array[i] = nil;
free(array);

同初始化时的注意事项相反,即使用 memset 等函数将内存填充为 0 也不会释放所赋值的对象。这非常危险,只会引起内存泄漏。对于编译器,必须明确地使用赋值给附有 __strong 修饰符变量的源代码。所以请注意,必须将 nil 赋值给所有数组元素。

并且,memcpy和realloc函数也会有危险,因为数组元素所赋值的对象有可能被保留在内存中或是重复被废弃,所以也禁止使用。


相关文章:

【iOS】OC高级编程 iOS多线程与内存管理阅读笔记——自动引用计数(二)

自动引用计数 前言ARC规则所有权修饰符**__strong修饰符**__weak修饰符__unsafe_unretained修饰符__autoreleasing修饰符 规则属性数组 前言 上一篇我们主要学习了一些引用计数方法的内部实现&#xff0c;现在我们学习ARC规则。 ARC规则 所有权修饰符 OC中&#xff0c;为了处…...

智能语音识别+1.2用SAPI实现文本转语音(100%教会)

欢迎来到智能语音识别系列的第二篇文章. 上一篇文章的地址在这:智能语音处理1.1下载需要的库(100%实现)-CSDN博客 想必上一篇的操作(文本转语音)已经成功实现了 接下来,我们要学习用SAPI技术去实现文本转语音 一.简单介绍SAPI技术 SAPI是架构在COM基础上的&#xff0c;微软…...

Unity导出微信小游戏后无法调起移动端输入框

参考官方demo 参考demo https://gitee.com/wechat-minigame/minigame-unity-webgl-transform/tree/main/Demo/API_V2 里面有对输入文本框适配的处理方法&#xff0c;还有一些其他功能展示 1 使用Unity打开/Demo/API目录&#xff0c;API示例开发版本为Unity 2022.3.14f1。 2 若…...

16.使用豆包将docker-compose的yaml转为k8s的yaml,安装各种无状态服务

文章目录 docker方式httpbinit-toolslinux-commandmyipreference docker-compose安装k8s方式 docker方式 httpbin A simple HTTP Request & Response Service https://httpbin.org/ https://github.com/postmanlabs/httpbin https://github.com/mccutchen/go-httpbin do…...

每日OJ_牛客_kotori和抽卡(二)_数学_C++_Java

目录 牛客_孩子们的游戏_约瑟夫环 题目解析 C代码 Java代码 牛客_孩子们的游戏_约瑟夫环 孩子们的游戏(圆圈中最后剩下的数)_牛客题霸_牛客网 描述&#xff1a; 每年六一儿童节&#xff0c;牛客都会准备一些小礼物和小游戏去看望孤儿院的孩子们。其中&#xff0c;有个游戏…...

整活 kotlin + springboot3 + sqlite 配置一个 SQLiteCache

要实现一个 SQLiteCache 也是很简单的只需要创建一个 cacheManager Bean 即可 // 如果配置文件中 spring.cache.sqlite.enable false 则不启用 Bean("cacheManager") ConditionalOnProperty(name ["spring.cache.sqlite.enable"], havingValue "t…...

JVM:运行时数据区和线程

一、运行时数据区概述 &#xff08;1&#xff09;整体架构 JVM 启动时&#xff0c;操作系统会为它分配相应的内存空间&#xff0c;接着 JVM 会对分配到的空间进行划分。当 JVM 退出&#xff0c;这些空间会被回收。JVM 将分配到的内存空间主要分成五部分&#xff1a;程序计数器…...

Lucene.NET + Jieba分词:核心词典与停用词配置详解

文章目录 前言一、dict.txt&#xff1a;核心分词词典1. 文件作用2. 文件格式3. 配置方法 二、cn_synonym.txt&#xff1a;同义词扩展库1. 文件作用2. 文件格式3. 在 Lucene 中使用 三、stopwords.txt&#xff1a;停用词表1. 文件作用2. 文件格式3. 配置方法 四、实战&#xff1…...

软件测试之测试数据生成(Excel版)

这是Excel生成测试数据的函数使用 1.时间 1.1.时间 例生成2022-05-01之前一年内任意时间点: =TEXT("2022-05-01"-RAND()-RANDBETWEEN(1,365),"yyyy-mm-dd hh:mm:ss")1.2.年月日 yyyy-mm-dd 以当前时间生成10年的日期 =TEXT(NOW()-RAND()-RANDBETWE…...

局域网内Docker镜像共享方法

在局域网内将Docker镜像构建并传输到另一台电脑&#xff0c;可以通过以下几种方法实现。以下是具体步骤及注意事项&#xff0c;结合不同场景的适用方案&#xff1a; 方法一&#xff1a;使用 docker save 和 docker load 传输镜像文件 步骤说明 在构建机上保存镜像 通过 docker…...

解决WinEdt编辑器出现文字不会适应软件宽度的问题

解决WinEdt编辑器出现文字不会适应软件宽度的问题 问题描述解决 问题描述 在使用WinEdt编辑Latex文本时&#xff0c;发现突然动了下键盘&#xff0c;或者突然就在编辑文本时不能自动换行&#xff0c;而是超出了软件屏幕的宽度。 解决 按住ctrl w &#xff0c;直到界面变成下…...

跨境电商管理转型:日事清通过目标管理、流程自动化助力智优美科技项目管理升级与目标落地复盘

1.客户背景介绍 深圳市智优美科技有限公司是一家专业从事外贸B2C的电子商务公司&#xff0c;公司总部位于深圳市宝安区&#xff0c;旗下拥有三家子公司。目前销售的品类有&#xff1a;家居用品、电子产品、电子配件产品等&#xff0c;在深圳外贸电商行业销售额稳居行业前10名。…...

高防CDN、高防IP vs 高防服务器:核心优势与选型指南

一、高防服务器的核心局限 高防服务器是指通过机房部署硬件防火墙&#xff08;如集群防火墙、流量清洗设备&#xff09;来防御DDoS攻击的物理或虚拟服务器。其核心问题在于&#xff1a; 单点防御风险&#xff1a;依赖单一服务器硬扛攻击&#xff0c;若攻击流量超过防御阈值&am…...

入门-C编程基础部分:5、变量

飞书文档https://x509p6c8to.feishu.cn/wiki/PVnawQn5DiVhHhkMApqcDyDvnWg 变量的作用&#xff1f; 存储程序运行时&#xff0c;需要存储一些可能会变化的数据。 C 中每个变量都有特定的类型&#xff0c;类型决定了变量存储的大小和布局。 变量的名称可以由字母、数字和下划…...

Kafka深度解析与实战应用

Kafka深度解析与实战应用 作者&#xff1a;LedgerX技术团队 发布日期&#xff1a;2025年4月16日 引言 在当今数字时代&#xff0c;数据已成为企业的核心资产&#xff0c;而高效处理大规模数据流的能力则成为现代后端系统的关键挑战之一。Apache Kafka作为一个分布式流处理平台…...

数学教学通讯杂志数学教学通讯杂志社数学教学通讯编辑部2025年第6期目录

课程教材教法 “课程思政”视域下的高中数学教学探索与实践——以“函数概念的发展历程”为例 赵文博; 3-617 PBL教学模式下高中统计教学的探索与实践——以“随机抽样&#xff08;第一课时&#xff09;”为例 陈沛余; 7-10 “三新”背景下的高中数学教学困境与应对…...

【JavaEE初阶】多线程重点知识以及常考的面试题-多线程进阶(二)

本篇博客给大家带来的是多线程中synchronize的实现原理和JUC(java.util.concurrent) 常见类的相关知识点. &#x1f40e;文章专栏: JavaEE初阶 &#x1f680;若有问题 评论区见 ❤ 欢迎大家点赞 评论 收藏 分享 如果你不知道分享给谁,那就分享给薯条. 你们的支持是我不断创作的…...

Flutter PIP 插件 ---- iOS Video Call 自定义PIP WINDOW渲染内容

以下是一篇关于在 iOS 中实现画中画(PiP)功能的技术博客: iOS 画中画(PiP)功能实现指南 效果 简介 画中画(Picture in Picture, PiP)是一项允许用户在使用其他应用时继续观看视频内容的功能。本文将详细介绍如何在 iOS 应用中实现 PiP 功能&#xff0c;包括自定义内容渲染和…...

【正点原子STM32MP257连载】第四章 ATK-DLMP257B功能测试——4G模块ME3630测试

1&#xff09;实验平台&#xff1a;正点原子ATK-DLMP257B开发板 2&#xff09;浏览产品&#xff1a;https://www.alientek.com/Product_Details/135.html 3&#xff09;全套实验源码手册视频下载&#xff1a;正点原子资料下载中心 文章目录 第四章 ATK-DLMP257B功能测试——4G模…...

高并发内存池(四):内存释放原理与实现

前言&#xff1a;经过前3期的攻坚&#xff0c;我们已完整实现了内存动态申请的核心模块。接下来将进入关键阶段——内存释放机制的理解与实现&#xff0c;这是构建完整 高并发内存池 的最后一块技术拼图。该模块完成后&#xff0c;项目主体架构将基本成型&#xff08;达90%&…...

【正点原子STM32MP257连载】第四章 ATK-DLMP257B功能测试——EEPROM、SPI FLASH测试 #AT24C64 #W25Q128

1&#xff09;实验平台&#xff1a;正点原子ATK-DLMP257B开发板 2&#xff09;浏览产品&#xff1a;https://www.alientek.com/Product_Details/135.html 3&#xff09;全套实验源码手册视频下载&#xff1a;正点原子资料下载中心 文章目录 第四章 ATK-DLMP257B功能测试——EEP…...

《突破控件限制:用Qt绘图API解锁高级界面定制能力》

一、基本概念 虽然 Qt 已经内置了很多的控件&#xff0c;但是不能保证现有控件就可以应对所有场景。很多时候我们需要更强的 “自定制” 能力。 Qt 提供了画图相关的 API&#xff0c;允许我们在窗口上绘制任意的图形形状来完成更复杂的界面设计 所谓的 “控件” 本质上也是通…...

MyBatis-Plus 中BaseMapper接口是如何加速微服务内部开发的?

假设我们有一个简单的微服务项目&#xff0c;需要对 User 实体进行基本的数据库操作。 场景一&#xff1a;使用原生 MyBatis 的开发流程 (作为对比) 定义实体类 (Entity): // package com.yourcompany.usermicroservice.entity; public class User {private Long id;private S…...

AIGC-十款数据分析类智能体完整指令直接用(DeepSeek,豆包,千问,Kimi,GPT)

Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列Scratch编程案例软考全系列Unity3D学习专栏蓝桥系列AIGC(GPT、DeepSeek、豆包、千问、Kimi)👉关于作者 专注于Android/Unity和各种游戏开发技巧,以及各种资…...

鸿蒙应用(医院陪诊系统)开发篇1·主页面的tabs布局

引言&#xff1a; 首先可在鸿蒙开发者官网找到DevEco Studio的安装教程。 安装好了之后&#xff0c;我们开始开发。 知识点&#xff1a; tabs布局&#xff0c;鸿蒙官方文档地址&#xff1a;https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/ts-contai…...

【大模型】DeepSeek + Coze 打造个人专属AI智能体使用详解

目录 一、前言 二、AI智能体介绍 2.1 什么是AI智能体 2.2 AI智能体核心能力 2.3 AI智能应用场景 三、coze 介绍 3.1 coze是什么 3.1.1 平台概述 3.1.2 平台适用人群 3.2 平台核心功能 3.3 coze可以做什么 3.4 为什么选择coze 四、coze 搭建AI智能体操作实践 4.1 搭…...

7.(vue3.x+vite)弹性布局(flex布局)

1:效果截图 2:代码实现 <template><span style="font-size: 20px">右边固定,左边自适应</span><div class=<...

Python基础总结(五)之字典

文章目录 一、字典的格式二、字典的操作2.1 增加项2.1.1 直接增加项2.1.1 formkeys方法 2.2 删除项2.2.1 clear()方法2.2.2 pop()方法 2.3 修改项2.3.1 直接修改2.3.2 update()方法 2.4 查找项2.4.1 get()方法2.4.2 直接查询2.4.3 items()方法2.4.4 keys()方法2.4.5 values()方…...

MCP简介:重构人机交互底层逻辑

在人工智能技术飞速发展的今天&#xff0c;大语言模型&#xff08;LLM&#xff09;的应用场景正不断拓展&#xff0c;但模型与外部系统之间的连接方式却成为制约其潜力发挥的关键瓶颈。为了解决这一难题&#xff0c;由AI领域顶尖公司Anthropic&#xff08;Claude模型背后的开发…...

LangChain缓存嵌入技术完全指南:CacheBackedEmbedding原理与实践(附代码示例)

一、嵌入缓存技术背景与应用场景 1.1 为什么需要嵌入缓存&#xff1f; 算力消耗问题&#xff1a;现代嵌入模型&#xff08;如text-embedding-3-small&#xff09;单次推理需要约0.5-1秒/文本 资源浪费现状&#xff1a;实际业务中约30%-60%的文本存在重复计算 成本压力&#…...

国产DPU芯片+防火墙,能否引领网络安全新跨越?

近日&#xff0c;国内首款搭载国产DPU芯片的800Gbps下一代防火墙——中科网威NSFW - 12000正式发布&#xff0c;引发行业广泛关注。 国产DPU芯片与防火墙的结合&#xff0c;正在推动网络安全领域实现技术突破与体系升级。以下从技术特性、应用场景和产业价值三个维度分析其引领…...

Spark-SQL与Hive的连接及数据处理全解析

Spark-SQL与Hive的连接及数据处理全解析 在大数据处理领域&#xff0c;Spark-SQL和Hive都是重要的工具。今天就来聊聊Spark-SQL如何连接Hive以及相关的数据处理操作。 Spark-SQL连接Hive有多种方式。内嵌Hive虽然使用简单&#xff0c;直接就能用&#xff0c;但在实际生产中…...

ArcGIS Desktop使用入门(四)——9版本与10版本区别

系列文章目录 ArcGIS Desktop使用入门&#xff08;一&#xff09;软件初认识 ArcGIS Desktop使用入门&#xff08;二&#xff09;常用工具条——标准工具 ArcGIS Desktop使用入门&#xff08;二&#xff09;常用工具条——编辑器 ArcGIS Desktop使用入门&#xff08;二&#x…...

使用 chromedriver 实现网络爬虫【手抄】

1、引用 selenium 包 <dependency><groupId>org.seleniumhq.selenium</groupId><artifactId>selenium-java</artifactId><version>4.29.0</version> </dependency> <dependency><groupId>org.seleniumhq.seleniu…...

ERROR: Unknown host CPU architecture: arm64

1、先检查NDK版本是否支持arm64&#xff0c;NDK版本21.3以上 2、检查gradle中&#xff0c;有关NDK版本是否设置arm64-v8a 例如&#xff1a; ndkVersion "21.4.7075529"ndk {abiFilters "armeabi-v7a","arm64-v8a"} local.properties中&#x…...

从 SQL2API 到 Text2API:开启数据应用开发的新征程

在技术革新浪潮的席卷下&#xff0c;数据应用开发领域正经历着深刻变革。曾经&#xff0c;构建数据 API 需要开发者具备扎实的数据库知识和编程技能&#xff0c;手动编写复杂的 SQL 查询与 API 代码&#xff0c;这一过程不仅耗时费力&#xff0c;还将众多非技术人员阻挡在数据应…...

OpenCv高阶(四)——角点检测

一、角点检测 在计算机视觉中&#xff0c;角点检测是识别图像中局部区域&#xff08;角点&#xff09;的关键技术&#xff0c;这些区域通常是两条或多条边缘的交点&#xff0c;具有丰富的结构信息&#xff0c;常用于图像匹配、跟踪、三维重建等任务。 Harris角点检测算法是一…...

centos8 部署 openstack

在 CentOS 8 上部署 OpenStack 是一个复杂的过程&#xff0c;涉及多个组件的安装和配置。OpenStack 是一个开源的云计算平台&#xff0c;它提供了基础设施即服务&#xff08;IaaS&#xff09;的功能。下面我将指导你通过基本的步骤来部署 OpenStack。 前提条件 系统要求&#…...

智能云图库-8-AI编辑

一、基础图片编辑​ 需求分析​ 在日常的图片管理中&#xff0c;用户经常需要对图片进行简单处理&#xff0c;比如裁剪多余部分、旋转图片、放大缩小尺寸等。 因此&#xff0c;我们首先要引入基础图片编辑功能&#xff0c;帮助用户快速完成以下操作&#xff1a; 裁剪&#…...

libwebsocket建立服务器需要编写LWS_CALLBACK_ADD_HEADERS事件处理

最近在使用libwebsocket&#xff0c;感觉它搭建Http与websocket服务器比较简单&#xff0c;不像poco库那么庞大&#xff0c;但当我使用它建立websocket服务器后&#xff0c;发现websocket客户端连接一直没有连接成功&#xff0c;不知道什么原因&#xff0c;经过一天的调试&…...

L1-002 打印沙漏

L1-002 打印沙漏 - 团体程序设计天梯赛-练习集 (pintia.cn) 本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个“*”&#xff0c;要求按下列格式打印 ************ *****所谓“沙漏形状”&#xff0c;是指每行输出奇数个符号&#xff1b;各行符号中心对齐&#…...

JSP技术入门指南【一】利用IDEA从零开始搭建你的第一个JSP系统

Jsp技术入门指南【一】利用IDEA从零开始搭建你的第一个JSP系统 前言一、什么是JSP1.1 JSP是干什么的&#xff1f;1.2 JSP与Servlet的关系是什么&#xff1f; 二、在Idea中创建第一个JSP系统三、JSP和HTML的差别3.1 格式区别3.2 注释区别 前言 在前面的内容中&#xff0c;我们已…...

NLP高频面试题(四十四)——RLHF过程中的马尔科夫决策过程及对话场景MDP设计

什么是马尔科夫决策过程(MDP)? 马尔科夫决策过程(MDP)是描述序贯决策问题的数学框架,由五元组( (S, A, P, R, \gamma) )组成,其中: (S):状态集合,描述环境的所有可能状态。(A):动作集合,描述智能体可以采取的所有可能动作。(P):状态转移概率函数,表示从一个状态…...

青少年编程与数学 02-016 Python数据结构与算法 24课题、密码学算法

青少年编程与数学 02-016 Python数据结构与算法 24课题、密码学算法 课题摘要:一、对称加密算法AES&#xff08;高级加密标准&#xff09;DES&#xff08;数据加密标准&#xff09;3DES&#xff08;三重数据加密标准&#xff09; 二、非对称加密算法RSAECC&#xff08;椭圆曲线…...

艺术字体AI生成阿里云WordArt锦书、通义万相、SiliconFlow、Pillow+OpenCV本地生成艺术字体

基于您的需求&#xff0c;结合最新API技术和搜索结果&#xff0c;以下是Python调用主流艺术字API的代码案例及对应充值链接方案&#xff1a; 一、大厂API服务&#xff08;付费方案&#xff09; 1. 阿里云WordArt锦书API # 文字纹理生成&#xff08;需安装dashscope&#xff…...

GIS开发笔记(7)结合osg及osgEarth实现不同高度下的三个圆形区域形成的三维覆盖轮廓区域绘制

一、实现效果如下&#xff1a; 二、实现原理 输入四个坐标点&#xff0c;第一个点为中心点&#xff0c;第二三四个点分别以中心点与地面垂线所在线上的各自高度水平面的交点为圆心旋转360进行圆形区域绘制&#xff0c;然后将三个不同高度上的圆形区域进行结合形成三维覆盖区域…...

解决 Kubernetes 调度器启动报错:缺少 Bind 插件

解决 Kubernetes 调度器启动报错&#xff1a;缺少 Bind 插件 问题描述 在启动自定义 Kubernetes 调度器时&#xff0c;出现了以下错误&#xff1a; I0416 17:08:41.420188 68788 configfile.go:57] "KubeSchedulerConfiguration v1beta2 is deprecated in v1.25, wil…...

Spring Batch 专题系列(六):并行处理与性能优化

1. 引言 在上一篇文章中,我们学习了 Spring Batch 的错误处理机制(Skip、Retry、Restart 和 Listener),掌握了如何提升作业的健壮性。随着数据量的增加,批处理任务的性能成为关键挑战。Spring Batch 提供了强大的并行处理功能,包括多线程 Step、分区(Partitioning)和并…...

WPF 从Main()方法启动

1.去掉App.xaml StartupUri“MainWindow.xaml” 只会让App.g.cs 不生成这行代码&#xff0c;但是还是会生成的App.g.cs文件中生成Main方法 this.StartupUri new System.Uri("MainWindow.xaml", System.UriKind.Relative);默认的App.xaml的生成操作是 应用程序定义…...

记录小程序第一次调用Api,基于腾讯云Serverless函数,实现小程序的成功接入api,以及数据调用

目录 创建腾讯云个人账户新建severless应用建立函数URL小程序中调用api示例 创建腾讯云个人账户 百度搜索即可&#xff0c;并注册 新建severless应用 作者以github下载的某Api为例&#xff0c;这里不展示具体Api&#xff0c;只关注操作即可&#xff0c;相信都是互通的 在腾…...