【2025 Rust学习 --- 11 实用工具特型01】
清理特型Drop
当一个值的拥有者消失时,Rust 会丢弃(drop)该值。丢弃一个值就必须释放 该值拥有的任何其他值、堆存储和系统资源。
丢弃可能发生在多种情况下:
- 当变量超出作用域时;
- 在表达式语句的末尾;
- 当截断一个向量时,会从其末尾移除元素
struct Appellation {name: String,nicknames: Vec<String>
}
每当 Appellation 被丢弃时,Rust 都会自动清理所有这些内容,无须你进行任何进一步的编码。也可以通过实现 std::ops::Drop
特型来自定义 Rust 该如何丢弃此类型的值:
trait Drop {fn drop(&mut self);
}
Drop 的实现类似于 C++ 中的析构函数或其他语言中的终结器。
当一个值被丢弃时,如果它实现了 std::ops::Drop
,那么 Rust 就会调用它的 drop 方 法,然后像往常一样继续丢弃它的字段或元素拥有的任何值。这种对 drop 的隐式调用是调用该方法的唯一途径。如果你试图显式调用该方法,那么 Rust 会将 其标记为错误。
Rust 在丢弃某个值的字段或元素之前会先对值本身调用 Drop::drop,该方法收到的值仍然是已完全初始化的。因此,在 Appellation 类型的 Drop 实现 中可以随意使用其字段:
impl Drop for Appellation {fn drop(&mut self) {print!("Dropping {}", self.name);if !self.nicknames.is_empty() {print!(" (AKA {})", self.nicknames.join(", "));}println!(""); }
}
{let mut a = Appellation {name: "Zeus".to_string(),nicknames: vec!["cloud collector".to_string(),"king of the gods".to_string()]};println!("before assignment");a = Appellation { name: "Hera".to_string(), nicknames: vec![] };println!("at end of block");
}
将第二个 Appellation 赋值给 a 时,就会丢弃第一个 Appellation,而当我们离开 a 的作用域时,就会丢弃第二个 Appellation。
String 在内部使用 Vec 来保存它 的文本,因此 String 不需要自己实现 Drop,它会让 Vec 负责释放这些字符。
一个值可能会从一个地 方移动到另一个地方,但 Rust 只会丢弃它一次。
如果一个类型实现了 Drop,就不能再实现 Copy 特型了。如果类型是 Copy 类 型,就表示简单的逐字节复制足以生成该值的独立副本。
限界特型Sized
固定大小类型是指其每个值在内存中都有相同大小的类型。
Sized
是 Rust 中的一个特殊 trait,它表示一个类型在编译时具有已知的大小。这个 trait 由编译器自动实现,并且对于所有具有固定大小的类型都是默认实现的。理解 Sized
特性非常重要,因为它影响了如何使用泛型、trait 对象和其他高级特性。
Sized
的作用
-
确保类型有已知大小:当一个类型实现了
Sized
trait,意味着它的大小可以在编译时确定。这对于许多操作来说是必要的,比如将值放在栈上或作为函数参数传递。 -
默认约束:在 Rust 中,泛型参数默认要求实现
Sized
trait。这意味着如果你定义了一个泛型函数或结构体,默认情况下它只能接受那些在编译时大小已知的类型。
?Sized
和 Sized
的区别
有时你可能希望放宽对类型的大小限制,允许它们可以是动态大小(DST, Dynamically Sized Type)。为此,Rust 提供了 ?Sized
语法,这表明类型不一定需要实现 Sized
。例如:
fn print_type_size<T: ?Sized>(t: &T) {println!("Type T might not be sized");
}
在这个例子中,T
可以是任何类型,包括那些没有固定大小的类型,如切片 [T]
或者特质对象 dyn Trait
。
动态大小类型 (DST)
Rust 支持几种动态大小类型,这些类型的大小只有在运行时才能确定。常见的 DST 包括:
- 切片
[T]
- 特质对象
dyn Trait
- 裸指针到 DST,如
*const [T]
或*mut dyn Trait
由于这些类型的大小无法在编译时确定,因此它们不能直接存储在栈上或作为普通变量使用。相反,它们通常通过指针(如 &[T]
、Box<dyn Trait>
)来间接引用。
使用场景
-
泛型编程:当你编写泛型代码时,默认情况下你的泛型参数是
Sized
的。如果你想让泛型参数接受动态大小类型,你需要显式地指定?Sized
。 -
特质对象:当你创建特质对象(如
Box<dyn Trait>
或&dyn Trait
)时,特质本身并不实现Sized
,因为特质对象的实际大小是在运行时决定的。 -
结构体和枚举:如果结构体或枚举包含字段或变体,这些字段或变体必须是
Sized
的,除非你使用了特殊的语法(如裸指针)来处理动态大小类型。
示例代码
下面是一个简单的例子,展示了 Sized
和 ?Sized
的使用:
// 这个函数只接受具有已知大小的类型
fn only_sized<T: Sized>(t: T) {// 函数体...
}// 这个函数可以接受任何类型,包括动态大小类型
fn also_unsized<T: ?Sized>(t: &T) {// 函数体...
}struct Wrapper<T: ?Sized> {value: Box<T>,
}fn main() {only_sized(42); // OK, i32 实现了 Sized// only_sized([1, 2, 3]); // 错误,数组的大小未知also_unsized(&42); // OK, &i32 实现了 ?Sizedalso_unsized(&[1, 2, 3]); // OK, &[i32] 实现了 ?Sizedlet boxed_slice = Wrapper { value: Box::new([1, 2, 3]) };
}
only_sized
函数只能接受实现了 Sized
的类型,而 also_unsized
函数则更加灵活,它可以接受任何类型的引用,包括那些动态大小的类型。此外,Wrapper
结构体能够包含动态大小类型,因为它使用了 Box<T>
来间接持有数据。
Rust 中的几乎所有类型都是固定大小的,比如每个 u64 占用 8 字节,每个 (f32, f32, f32) 元组占用 12 字节。甚至枚举也是有大小的,也就是说,无论实际存在的是哪个变体,枚举总会占据足够的空间来容纳其最大的变体。尽管 Vec 拥有一个 大小可变的堆分配缓冲区,但 Vec 值本身是指向“缓冲区、容量和长度”的指针
,因此 Vec 也是一个固定大小类型。
所有固定大小类型都实现了 std::marker::Sized
特型,该特型没有方法或 关联类型。Rust 自动为所有适用的类型实现了 std::marker::Sized 特型, 你不能自己实现它。Sized 的唯一用途是作为类型变量的限界:像 T: Sized 这样的限界要求 T 必须是在编译期已知的类型。由于 Rust 语言本身会使用这种类型的特型为具有某些特征的类型打上标记,因此我们将其称为标记特型
。
然而,Rust 也有一些无固定大小类型,它们的值大小不尽相同。例如,字符串 切片类型 str(注意没有 &)就是无固定大小的。字符串字面量 “diminutive” 和 “big” 是对占用了 10 字节和 3 字节的 str 切片的引用。像 [T](同样没有 &)这样的数组切片类型也是无固 定大小的,即像 &[u8] 这样的共享引用可以指向任意大小的 [u8] 切片。因为 str 类型和 [T] 类型都表示不定大小的值集,所以它们是无固定大小类型。
Rust 中另一种常见的无固定大小类型是 dyn
类型,它是特型对象的引用目标
,是指向实现了给定特型的某个值的指针
。例如,类型 &dyn std::io::Write 和 Box
是指向实现了 Write 特型的某个值的指针。引用目标可能是文件、网络套接字,或某种实现了 Write 的自定义类型。由于实现了 Write 的类型集是开放式的,因此dyn Write
作为一个类型也是无固定大小的,也就 是说它的值可以有各种大小。
Rust 不能将无固定大小的值存储在变量中或将它们作为参数传递。你只能通过 像 &str 或 Box 这样的本身是固定大小的指针来处理它们。
指向无固定大小值的指针始终是一个胖指针,宽度为两个机器字: 指向切片的指针带有切片的长度,特型对象带有指向方法实现的虚表的指针。 特型对象和指向切片的指针在结构上很像。这两种类型,胖指针都会补齐类型中缺少的信息——它携 带着长度或虚表指针。既然欠缺静态信息,那就用动态信息来弥补。 由于无固定大小类型处处受限,因此大多数泛型类型变量应当被限制为固定大小 的 Sized 类型。
事实上,鉴于这种情况的普遍性,Sized 已经成为 Rust 中的 隐式默认值:如果你写 struct S<T> { ... }
,那么 Rust 会将其理解为 struct S<T:Sized> { ... }
。如果你不想以这种方式约束 T,就必须将 其明确地排除,写成 struct S<T:?Sized> { ... }
。?Sized
语法专用 于这种情况,意思是“不要求固定大小的”。如果你写 struct S <T: ?Sized>{ b: Box }
,那么 Rust 将允许写成 S<str> 和 S<dyn Write>
,这样这 两个 Box 就变成了胖指针,而不像 S<i32> 和 S<String>
的 Box 那样只是普通指针。
尽管存在一些限制,但无固定大小类型能让 Rust 的类型系统工作得更顺畅。偶尔会遇到类型变量上的 ?Sized
限界,这几乎总是表明 “给定的类型只能通过指针访问”,并能让其关联的代码与切片对象和特型对象以及普通值一起使用。当类型变量具有?Sized
限界时,它的大小不确定,既可能是固定大小,也可能不是。
【柔性数组】除了切片对象和特型对象,还有另一种无固定大小类型。结构体类型的最后一个字段(而且只能是最后一个)可以是无固定大小的,并且这样的结构体本身也是 无固定大小的。例如,Rc 引用计数指针的内部实现是指向私有类型 RcBox 的指针,后者把引用计数和 T 保存在一起。下面是 RcBox 的简化定义:
struct RcBox<T: ?Sized> {ref_count: usize, value: T,
}
Rc <T>
是引用计数指针,其中的 value 字段是 Rc <T>
对其进行引用计数的 T 类型。Rc<T>
会解引用成指向 value 字段的指针。ref_count 字段会保存其 引用计数。 真正的 RcBox 只是标准库的一个实现细节,无法在外部使用。但假设我们正在使用前面这种定义,那么就可以将此 RcBox 与固定大小类型一起使用,比如 RcBox <String>
的结果是一个固定大小的结构体类型。
或者也可以将它与无固 定大小类型一起使用,比如 RcBox<dyn Display>
就成了无固定大小的结构体类型。 不能直接构建 RcBox<dyn Display>
值,而应该先创建一个普通的固定大小 的 RcBox,并让其 value 类型实现 Display,比如 RcBox<String>
。然后 Rust 就会允许你将引用 &RcBox <String>
转换为胖引用 &RcBox<dyn Display>
:
let boxed_lunch: RcBox<String> = RcBox {ref_count: 1,value: "lunch".to_string()
};
use std::fmt::Display;
let boxed_displayable: &RcBox<dyn Display> = &boxed_lunch;
将值传给函数时会发生隐式转换,可以将 &RcBox 传给需 要 &RcBox 的函数:
fn display(boxed: &RcBox<dyn Display>) {println!("For your enjoyment: {}", &boxed.value);
}
display(&boxed_lunch);
深拷贝特型Clone
std::clone::Clone 特型适用于可复制自身的类型。
trait Clone: Sized {fn clone(&self) -> Self;fn clone_from(&mut self, source: &Self) { // Self类型标记*self = source.clone()}
}
clone
方法应该为 self 构造一个独立的副本并返回它。由于此方法的返回类型是 Self,并且函数本来也不可能返回无固定大小的值,因此 Clone 特型也是扩展自 Sized 特型的,进而导致其实现代码中的 Self 类型被限界成了 Sized。
克隆一个值需要为它拥有的任何值分配副本,因此 clone 无论在时间消 耗还是内存占用方面都是相当昂贵的。例如,克隆 Vec 不仅会复制 此向量,还会复制它的每个 String 元素。这就是 Rust 不会自动克隆值,而是 要求你进行显式方法调用的原因。
像 Rc 和 Arc 这样的引用计数指针类型
属于例外,即克隆其中任何一个都只会增加引用计数并为你返回一个新指针。
clone_from
方法会把 self 修改成 source 的副本。clone_from 的默认定义只是克隆 source,然后将其转移给 *self。对于某些类 型,有一种更快的方法可以获得同样的效果。假设 s 和 t 都是 String。s = t.clone(); 语句必然会克隆 t,丢弃 s 的旧值,然后将克隆后的值转移给 s,这会进行一次堆分配和一次堆释放。但是如果属于原始 s 的堆缓冲区有足够的容量来保存 t 的内容,则不需要分配或释放:可以简单地将 t 的文本复制到 s 的缓冲区并调整长度。在泛型代码中,应该优先使用 clone_from,以便充分利用这种优化。
如果 Clone 实现只需要简单地对类型中的每个字段或元素进行 clone,然后从这些克隆结果中构造一个新值,并且认为 clone_from 的默认定义已经足够好了,那么 Rust 也可以帮你实现:只要在类型定义上方写 # [derive(Clone)]
就可以了。
标准库中几乎所有能合理复制的类型都实现了 Clone。不仅 bool、i32 等原始 类型实现了 Clone,String、Vec 和 HashMap 等容器类型也实现了 Clone。
而那些无法合理复制的类型(如 std::sync::Mutex
)则没有实现 Clone。像 std::fs::File
这样的类型虽然可以复制,但如果操作系统无法 提供必要的资源,则复制可能会失败。这些类型也没有实现 Clone,因为 clone 必须是不会失败的。作为替代,std::fs::File
提供了一个try_clone
方法,该方法会返回一个 std::io::Result
值,用以报告失败信息。
浅拷贝特型Copy
对于大多数类型,赋值时会移动值,而不是复制它们。移动值可以更简单地跟踪它们所拥有的资源。但是也有需要复制值的场景。
如果一个类型实现了 std::marker::Copy
标记特型,那么它就是 Copy 类型,允许通过逐位复制的方式产生副本。其定义 如下所示:
trait Copy: Clone { }
Copy 是一种对语言有着特殊意义的标记特型,因此只有当类型需要一个浅层的逐字节复制时,Rust 才允许它实现 Copy。拥有任何其他资源(比如堆缓冲区或操作系统句柄)的类型都无法实现 Copy。
任何实现了 Drop 特型的类型都不能是 Copy 类型。Rust 认为如果一个类型需要特殊的清理代码,那么就必然需要特殊的复制代码,因此不能是 Copy 类型。
可以使用 #[derive(Copy)]
让 Rust 为你派生出 Copy 实现。你会经常看到同时使用 #[derive(Copy, Clone)]
进行派生的代码。 在允许一个类型成为 Copy 类型之前务必慎重考虑。尽管这样做能让该类型更易于使用,但也对其实现施加了严格的限制。如果复制的开销很高,那么就不适合进行隐式复制。
Clone和Copy区别
Copy
特性
-
含义:当一个类型实现了
Copy
特性时,它意味着该类型的值可以被简单地通过位拷贝来复制。这意味着当你将一个值赋给另一个变量或将其作为参数传递给函数时,Rust 会自动创建该值的一个副本,而不是移动所有权。 -
语义:对于实现了
Copy
的类型来说,复制操作是浅拷贝,并且不会影响原始数据。例如,整数、浮点数、字符以及小的固定大小的数据类型通常都是Copy
的。 -
性能:因为只是简单地复制内存中的位,所以
Copy
操作是非常快速和高效的。 -
实现限制:并不是所有的类型都可以实现
Copy
。特别是那些包含动态分配资源(如堆上分配的内存)或者具有非复制语义(如文件句柄或网络连接)的类型,不能实现Copy
,因为简单的位复制无法正确处理这些资源的所有权和生命周期问题。 -
默认实现:如果一个类型只包含其他
Copy
类型,并且没有自定义析构函数(即没有实现Drop
trait),那么它可以自动派生Copy
。
#[derive(Copy, Clone)]
struct Point {x: i32,y: i32,
}
Clone
特性
-
含义:
Clone
特性允许你显式地调用.clone()
方法来创建一个对象的深拷贝。这意味着对于复杂类型,Clone
可能会执行更深层次的复制逻辑,以确保新旧对象独立于彼此。 -
语义:
Clone
可以用于任何需要深拷贝的场景,包括但不限于那些拥有堆分配数据的类型。开发者可以根据需要自定义Clone
的行为,以确保正确的复制语义。 -
性能:由于
Clone
可能涉及更深一层的数据结构复制,因此它的性能可能不如Copy
那么高效,具体取决于实现方式。 -
实现灵活性:几乎所有类型都可以实现
Clone
,包括那些管理动态资源的类型。但是,实现者必须确保正确处理所有相关资源,避免双重释放等问题。
struct ComplexType {data: String, // String 不是 Copy 的,因为它管理了堆上的资源
}impl Clone for ComplexType {fn clone(&self) -> Self {ComplexType {data: self.data.clone(), // 手动处理深拷贝}}
}
-
Copy
提供了一种轻量级的复制机制,适用于不需要关心所有权转移的小而简单的类型; -
Clone
则提供了一种更加通用和可控的方式来进行深拷贝,适用于各种类型,尤其是那些需要管理复杂资源的类型。
相关文章:
【2025 Rust学习 --- 11 实用工具特型01】
清理特型Drop 当一个值的拥有者消失时,Rust 会丢弃(drop)该值。丢弃一个值就必须释放 该值拥有的任何其他值、堆存储和系统资源。 丢弃可能发生在多种情况下: 当变量超出作用域时;在表达式语句的末尾;当…...
关于Linux PAM模块下的pam_listfile
讲《Linux下禁止root远程登录访问》故事的时候,说好会另开一篇讲讲pam_listfile。我们先看看pam_listfile的man文档怎么介绍的。 下面这些就好比人物的简介,甚是恼人;让人看得不明就里,反正“他大舅他二舅都是他舅”。可以直接跳…...
根据中文名称首字母进行分组
很多项目中,需要用到中文名称到首字母进行分组,例如:城市、游戏等等。。。 /*** 将集合数据按照汉字首字母分组排序** param list* return*/public Map<String, Object> screenManufacturer(List<Game> list) {Set<String>…...
springboot 集成 etcd
springboot 集成 etcd 往期内容 ETCD 简介docker部署ETCD 前言 好久不见各位小伙伴们,上两期内容中,我们对于分布式kv存储中间件有了简单的认识,完成了docker-compose 部署etcd集群以及可视化工具 etcd Keeper,既然有了认识&a…...
人工智能-数据分析及特征提取思路
1、概况 基于学生行为数据预测是否涉黄、涉黑等。 2.数据分析 数据分析的意义包括得到数据得直觉、发掘潜在的结构、提取重要的变量、删除异常值、检验潜在的假设和建立初步的模型。 2.1数据质量分析 2.1.1数据值分析 查看数据类型: 首先明确各字段的数据类型…...
设计模式 行为型 状态模式(State Pattern)与 常见技术框架应用 解析
状态模式(State Pattern)是一种行为型设计模式,它允许对象在内部状态改变时改变其行为,使得对象看起来好像修改了它的类。这种设计模式的核心思想是将对象的状态和行为封装成不同的状态类,通过状态对象的行为改变来避免…...
Android 系统签名 keytool-importkeypair
要在 Android 项目中使用系统签名并将 APK 打包时与项目一起打包,可以按照以下步骤操作: 步骤 1:准备系统签名文件 从 Android 系统源码中获取系统签名文件,通常位于 build/target/product/security 目录下,包括 pla…...
ubuntu22.04 gcc,g++从10.5切换到低版本9.5
一、安装gcc-9.5 mkdir gcc cd gcc sudo apt-get download $(apt-cache depends --recurse --no-recommends --no-suggests --no-conflicts --no-breaks --no-replaces --no-enhances --no-pre-depends gcc-9 | grep -v i386 | grep "^\w") sudo dpkg -i *.deb sudo…...
Microsoft 已经弃用了 <experimental/filesystem> 头文件
#define _CRT_SECURE_NO_WARNINGS 1 #define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING 1 //Microsoft 已经弃用了 <experimental / filesystem> 头文件,并计划在将来移除它。取而代之的是 C17 标准引入的 //<filesystem> 头文件…...
git 提交命令记录
1.已有本地和远程仓库 查看仓库远程地址: git remote -v 大量提交 git add . git commit -m "提交说明" git push 之后输入用户名密码 删除文件 git rm 文件名 替代git add 后面一样 2.全新提交 新建远程仓库 git init touch README.md git add . …...
Unity + Firebase + GoogleSignIn 导入问题
我目前使用 Unity版本:2021.3.33f1 JDK版本为:1.8 Gradle 版本为:6.1.1 Firebase 版本: 9.6.0 Google Sign In 版本为: 1.0.1 问题1 :手机点击登录报错 apk转化成zip,解压,看到/lib/armeabi-v…...
深度学习的加速器:Horovod,让分布式训练更简单高效!
什么是 Horovod? Horovod 是 Uber 开发的一个专注于深度学习分布式训练的开源框架,旨在简化和加速多 GPU、多节点环境下的训练过程。它以轻量级、易用、高性能著称,特别适合需要快速部署分布式训练的场景。Horovod 的名字来源于俄罗斯传统舞…...
AI刷题-异或编码、拼凑单词 chi
目录 一、异或编码 问题描述 测试样例 解题思路: 问题理解 解题思路 数据结构选择 算法步骤 最终代码: 运行结果: 二、拼凑单词 chi 问题描述 测试样例 解题思路: 问题理解 数据结构选择 算法步骤 最终代码&a…...
xml简介
目录 基本语法特点及应用场景一个简单示例 xml(全称eXtensible Markup Language)是一种用于存储和传输数据的标记语言,跨平台并且跨语言,xml内容较多,这篇文章会介绍一些基础的内容。 基本语法 xml文档通常以xml声明开…...
MYSQL------MySQL 复制MySQL Cluster 架构
MySQL 复制 安装配置 主服务器配置 首先,在主服务器的配置文件(my.cnf 或 my.ini)中添加以下基本配置: [mysqld] server-id 1 log-bin /var/log/mysql/mysql-bin.logserver-id:为服务器分配唯一的标识࿰…...
【人工智能】 用Python构建图像分类模型:从TensorFlow到PyTorch的全面指南
随着深度学习在计算机视觉领域的迅猛发展,图像分类作为其核心任务之一,受到了广泛的关注。本文旨在详细介绍如何使用Python构建图像分类模型,从TensorFlow到PyTorch两个主流深度学习框架进行全面对比与实践。文章首先回顾了图像分类的基本概念…...
计算机网络 笔记 数据链路层 2
1,信道划分: (1)时分复用TDM 将时间等分为“TDM帧”,每个TDM帧内部等分为m个时隙,m个用户对应m个时隙 缺点:每个节点只分到了总带宽的1/m,如果有部分的1节点不发出数据,那么就会在这个时间信道被闲置,利用…...
2024年度漏洞态势分析报告,需要访问自取即可!(PDF版本)
2024年度漏洞态势分析报告,需要访问自取即可!(PDF版本),大家有什么好的也可以发一下看看...
Apache Hop从入门到精通 第一课 揭开Apache Hop神秘面纱
一、Apache Hop是什么? 1、Apache Hop,简称Hop,全称为Hop Orchestration Platform,即Hop 工作编排平台,是一个数据编排和数据工程平台,旨在促进数据和元数据编排的所有方面。Hop让你专注于你想要解决的问题…...
Unity 人体切片三维可视化,可任意裁切切割。查看不同断层的图像。
Unity 人体切片三维可视化,真彩色,可任意裁切切割。查看不同断层的图像。 点击查看效果: 视频效果...
ModuleNotFoundError: No module named ‘podm.metrics‘报错等解决方法
ModuleNotFoundError: No module named podm.metrics’报错等解决方法 podm.metrics 在运行时报错: ModuleNotFoundError: No module named ‘podm.metrics’ 安装了podm后还是报错 解决方法: 查看安装位置 查看podm的安装位置,并打开到该…...
Java虚拟机运行时数据区域(内存模型)
程序计数器(线程私有内存) What:程序计数器是一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器。 程序控制流的指示器, 分支,循环,跳转,异常处理,线程…...
trf 4.10安装与使用-生信工具42
01 背景 DNA 中的串联重复(Tandem Repeat)指的是两个或多个相邻且近似的核苷酸模式的拷贝。Tandem Repeats Finder (TRF) 是一个程序,用于定位并显示 DNA 序列中的串联重复。用户只需提交一个以 FASTA 格式编写的序列,无需指定重…...
rom定制系列------小米max3安卓12 miui14批量线刷 默认开启usb功能选项 插电自启等
小米Max3是小米公司于2018年7月19日发布的机型。此机型后在没有max新型号。采用全金属一体机身设计,配备6.9英寸全面屏.八核处理器骁龙636,后置双摄像头1200万500万像素,前置800万像素.机型代码 :nitrogen.官方最终版为稳定版12.5…...
PySide6-UI界面设计
导论: PySide6和PyQt都是Python对Qt框架的绑定,允许开发者使用Qt创建平台的GUI应用程序。如果你正在开发商业项目,或者需要使用最新的QT6特性,PySide6是一个更好的选择。如果你更倾向于一个成熟的社区和丰富的资源,Py…...
Java创建线程的方式有哪些?
创建线程的方式 1. 继承 Thread 类 在 Java 中,当你启动一个线程时,实际上是调用了 Thread 类的 start() 方法。这个方法会执行以下几个步骤: 线程的状态转变:调用 start() 方法后,线程的状态从 NEW 转变为 RUNNABL…...
Ubuntu | PostgreSQL | 解决 ERROR: `xmllint` is missing on your system.
解决 sudo apt install apt-file sudo apt-file updatesudo apt-file search xmllint sudo apt install libxml2-utils执行 # postgres源码安装包解压文件夹中 make install make install问题 make -C src install make[2]: Entering directory /home/postgres/postgresql-1…...
Jenkins pipeline 发送邮件及包含附件
Jenkins pipeline 发送邮件及包含附件 设置邮箱开启SMTP服务 此处适用163 邮箱 开启POP3/SMTP服务通过短信获取TOKEN (保存TOKEN, 后面Jenkins会用到) Jenkins 邮箱设置 安装 Build Timestamp插件 设置全局凭证 Dashboard -> Manage Jenkins …...
基于深度学习的视觉检测小项目(十) 通过样式表改变界面的外观
一、创建色卡模板文件 在PS中打开之前创建的色卡文件,用吸管拾色器吸取各个色卡的色彩值: 并保存为JSON文件,color_card.json,文件保存在项目的/settings目录下: {"colors": {"RED": "#dc1…...
【Java基础】Stream流、文件File相关操作,IO的含义与运用
1. Java 流(Stream)、文件(File)和IO Java.io 包几乎包含了所有操作输入、输出需要的类。所有这些流类代表了输入源和输出目标。Java.io 包中的流支持很多种格式,比如:基本类型、对象、本地化字符集等等。 一个流可以理解为一个数据的序列。 输入流表…...
Java-日志-Slf4j-Log4j-logback
文章目录 SLF4J基础概念使用输出形式日志绑定桥接旧的框架实战 logback基础概念配置文件 Log4j概述 SLF4J 参考: https://www.cnblogs.com/shenStudy/p/15806951.html https://slf4j.org/ 基础概念 是什么?SLF4J(Simple Logging Facade fo…...
探索式测试
探索式测试是一种软件测试风格,它强调独立测试人员的个人自由和职责,为了持续优化其工作的价值,将测试学习、测试设计、测试执行和测试结果分析作为相互支持的活动,在整个项目实现过程中并行地执行。 选择合适的探索式测试方法我…...
LeetCode LCP17速算机器人
速算机器人:探索字符指令下的数字变换 在编程的奇妙世界里,我们常常会遇到各种有趣的算法问题,这些问题不仅考验我们的逻辑思维,还能让我们感受到编程解决实际问题的魅力。今天,就让我们一同探讨一个关于速算机器人的…...
Taro+Vue实现图片裁剪组件
cropper-image-taro-vue3 组件库 介绍 cropper-image-taro-vue3 是一个基于 Vue 3 和 Taro 开发的裁剪工具组件,支持图片裁剪、裁剪框拖动、缩放和输出裁剪后的图片。该组件适用于 Vue 3 和 Taro 环境,可以在网页、小程序等平台中使用。 源码 https:…...
ISP各模块功能介绍
--------声明,本文为转载整理------- ISP各个模块功能介绍: 各模块前后效果对比: 黑电平补偿(BLC) 在理想情况下,没有光照射的像素点其响应值应为0。但是,由于杂质、受热等其它原因的影响&…...
SQL-leetcode-584. 寻找用户推荐人
584. 寻找用户推荐人 表: Customer -------------------- | Column Name | Type | -------------------- | id | int | | name | varchar | | referee_id | int | -------------------- 在 SQL 中,id 是该表的主键列。 该表的每一行表示一个客户的 id、姓名以及推…...
新冠肺炎服务预约微信小程序的设计与实现ssm+论文源码调试讲解
第4章 系统设计 4.1 系统设计的原则 在系统设计过程中,也需要遵循相应的设计原则,这些设计原则可以帮助设计者在短时间内设计出符合设计规范的设计方案。设计原则主要有可靠性,安全性,可定制化,可扩展性,可…...
多模态人工智能在零售业的未来:通过GPT-4 Vision和MongoDB实现智能产品发现
多模态人工智能在零售业的未来:通过GPT-4 Vision和MongoDB实现智能产品发现 引言 想象一下,顾客在购物时只需上传一张他们所期望的服装或产品的照片,几分钟内便能收到来自他们最喜欢的商店的个性化推荐。这就是多模态人工智能在零售领域所带…...
3D目标检测数据集——kitti数据集
KITTI官网网址:The KITTI Vision Benchmark Suite 下载数据集:The KITTI Vision Benchmark Suite KITTI数据集论文:CMSY9 github可视化代码:GitHub - kuixu/kitti_object_vis: KITTI Object Visualization (Birdview, Volumetric LiDar point cloud )...
从CentOS到龙蜥:企业级Linux迁移实践记录(系统安装)
引言: 随着CentOS项目宣布停止维护CentOS 8并转向CentOS Stream,许多企业和组织面临着寻找可靠替代方案的挑战。在这个背景下,龙蜥操作系统(OpenAnolis)作为一个稳定、高性能且完全兼容的企业级Linux发行版࿰…...
Cocos二维Slider
1、可拖动区域计算 根据UI的世界坐标了宽高信息计算出handle的坐标范围 this.posMin new Vec2(this.node.worldPosition.x - this.uiSelf.contentSize.width * 0.5, this.node.worldPosition.y - this.uiSelf.contentSize.height * 0.5); this.posMax new Vec2(this.node.w…...
kubeneters-循序渐进Cilium网络(二)
文章目录 概要IP 地址配置接口配置解析结论 概要 接续前一章节,我们还是以这张图继续深入Cilium网络世界 IP 地址配置 通过检查 Kubernetes 集群的当前环境,可以获取实际的 IP 地址和配置信息。这些信息将被补充到之前的网络示意图中,以使…...
【再谈设计模式】模板方法模式 - 算法骨架的构建者
一、引言 在软件工程、软件开发过程中,我们经常会遇到一些算法或者业务逻辑具有固定的流程步骤,但其中个别步骤的实现可能会因具体情况而有所不同的情况。模板方法设计模式(Template Method Design Pattern)就为解决这类问题提供了…...
[开源]自动化定位建图系统(视频)
系统状态机: 效果展示: 1、 机器人建图定位系统-基础重定位,定位功能演示 2、 机器人建图定位系统-增量地图构建,手动回环检测演示 3、… 开源链接: https://gitee.com/li-wenhao-lwh/lifelong-backend Qt人机交互…...
Kali系统(Debian 10.3) 遇到的问题
目录 问题一:非问题 kali 基础官网与安装 问题二: 问题三: Kali系统 MySQL问题Cant connect to local MySQL server through socket /run/mysqld/mysqld.sock (2) 问题四:重新安装MySQL 也就是MariaDB(MariaDB 含 MySQL相关…...
P2249 【深基13.例1】查找
题目描述 输入 n 个不超过 109 的单调不减的(就是后面的数字不小于前面的数字)非负整数 a1,a2,…,an,然后进行 m 次询问。对于每次询问,给出一个整数 q,要求输出这个数字在序列中第一次出现的编号,如…...
【时时三省】(C语言基础)常见的动态内存错误3
山不在高,有仙则名。水不在深,有龙则灵。 ----CSDN 时时三省 对同一块动态内存多次释放 示例: 解决方法就是释放完把p等于空指针就好了 动态开辟的空间忘记释放 示例: 只有p能找到这块空间 只有p知道这块动态开辟的空间起始地…...
Three.js 性能优化:打造流畅高效的3D应用
文章目录 前言一、减少几何体复杂度(Reduce Geometry Complexity)二、合并几何体(Merge Geometries)三、使用缓冲区几何体(Use BufferGeometries)四、纹理压缩与管理(Texture Compression and M…...
CancerGPT :基于大语言模型的罕见癌症药物对协同作用少样本预测研究
今天我们一起来剖析一篇发表于《npj Digital Medicine》的论文——《CancerGPT for few shot drug pair synergy prediction using large pretrained language models》。该研究聚焦于一个极具挑战性的前沿领域:如何利用大语言模型(LLMs)在数…...
Clisoft SOS与CAD系统集成
Clisoft SOS与CAD系统集成 以下内容大部分来自官方文档,目前只用到与Cadence Virtuoso集成,其他还未用到,如有问题或相关建议,可以留言。 与Keysight ADS集成 更新SOS客户端配置文件sos.cfg,以包含支持ADS的模板&am…...