【2025 Rust学习 --- 11 实用工具特型01】

news2025/1/11 16:25:13

清理特型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。这意味着如果你定义了一个泛型函数或结构体,默认情况下它只能接受那些在编译时大小已知的类型。

?SizedSized 的区别

有时你可能希望放宽对类型的大小限制,允许它们可以是动态大小(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 实现了 ?Sized
    also_unsized(&[1, 2, 3]); // OK, &[i32] 实现了 ?Sized

    let 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 则提供了一种更加通用和可控的方式来进行深拷贝,适用于各种类型,尤其是那些需要管理复杂资源的类型。

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

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

相关文章

9 异常

如果你希望在软件调试上有所突破,或者想了解如何通过异常进行反调试,或者想自己写一个调试器,那么就必须要深入了解异常,异常与调试是紧密相连的,异常是调试的基础。 异常产生后,首先是要记录异常信息(异常的类型、异常发生的位置等),然后要寻找异常的处理函数,我们…

springBoot整合ELK Windowsb版本 (elasticsearch+logstash+kibana)

springBoot整合ELK Windowsb版本 【elasticsearchlogstashkibana】 下载软件启动服务1、elasticsearch2、kibana3、logstash 集成springboot1、添加依赖2、在logback.xml添加相关配置3、修改logstash 配置4、重启logstash 最后测试 下载软件 elasticsearch 官网 https://www.…

详解Sonar与Jenkins 的集成使用!

本文阅读前提 本文假设读者熟悉Jenkins和SonarQube的基础操作。 核心实现功能 Jenkins中运行的job来调用SonarScanner&#xff0c;最后可实现测试结果与SonarQube中同步查看。 Jenkins中安装Sonar相关插件 配置Sonarqube Dashboard>Manage Jenkins>Systems 指定son…

鸿蒙面试 2025-01-10

写了鉴权工具&#xff0c;你在项目中申请了那些权限&#xff1f;&#xff08;常用权限&#xff09; 位置权限 &#xff1a; ohos.permission.LOCATION_IN_BACKGROUND&#xff1a;允许应用在后台访问位置信息。 ohos.permission.LOCATION&#xff1a;允许应用访问精确的位置信息…

php 使用simplexml_load_string转换xml数据格式失败

本文介绍如何使用php函数解析xml数据为数组。 <?php$a <xml><ToUserName><![CDATA[ww8b77afac71336111]]></ToUserName><FromUserName><![CDATA[sys]]></FromUserName><CreateTime>1736328669</CreateTime><Ms…

【多空资金博弈】综合副图指标,资金做多线,短线做多雷达,中长线共振,大资金进场会涨等技术信号

如上图&#xff0c;副图指标【多空资金博弈】&#xff0c;红线做多资金线&#xff0c;绿色线为做空资金线&#xff0c;紫色柱线为短线做多雷达信号&#xff0c;紫色圆柱叠加文字为大资金进场信号&#xff0c;堆量柱线和紫色空心柱线为底部吸筹建仓信号&#xff0c;三条横向虚线…

Win11家庭版转专业版

Win11家庭版转专业版&#xff08;亲测有效&#xff09; 第一步 【断网】输入这个密钥&#xff1a; R8NJ8-9X7PV-C7RCR-F3J9X-KQBP6 第二步 点击下一步会自动重启 第三步 【联网】输入这个密钥&#xff1a; F3NWX-VFMFC-MHYYF-BCJ3K-QV66Y 注意 两次输入密钥的地方一致 …

【云商城】高性能门户网构建

第3章 高性能门户网构建 网站门户就是首页 1.OpenResty 百万并发站点架构 ​ 1).OpenResty 特性介绍 ​ 2).搭建OpenResty ​ 3).Web站点动静分离方案剖析 2.Lua语法学习 ​ 1).Lua基本语法 3.多级缓存架构实战 ​ 1).多级缓存架构分析 用户请求网站&#xff0c;最开始…

上海亚商投顾:沪指探底回升微涨 机器人概念股午后爆发

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 市场全天探底回升&#xff0c;沪指盘中跌超1.6%&#xff0c;创业板指一度跌逾3%&#xff0c;午后集体拉升翻红…

计算机毕业设计Python机器学习农作物健康识别系统 人工智能 图像识别 机器学习 大数据毕业设计 算法

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

游戏语音的历史是什么样的?

游戏中&#xff0c;离不开游戏社交。 无社交&#xff0c;不游戏&#xff0c;大家都深知社交在游戏体验中的重要性。 游戏语音的发展史是怎么样的&#xff1f;问了下AI&#xff0c;给我的回答是 早期阶段 1970年代&#xff1a;1970年代出现了第一个语音游戏“尤瓦尔的冒险”&am…

《解锁图像的语言密码:Image Caption 开源神经网络项目全解析》

《解锁图像的语言密码&#xff1a;Image Caption 开源项目全解析》 一、开篇&#xff1a;AI 看图说话时代来临二、走进 Image Caption 开源世界三、核心技术拆解&#xff1a;AI 如何学会看图说话&#xff08;一&#xff09;深度学习双雄&#xff1a;CNN 与 RNN&#xff08;二&a…

毕业设计选题

你是不是正在纠结毕业设计该如何完成&#xff1f;不知道该如何选题?同时又觉得定制太昂贵&#xff1f;你是不是还在为毕业论文不会写而苦恼&#xff1f; 当你看到这儿&#xff0c;就不用再纠结再苦恼了&#xff0c;周哥为你提供了计算机专业各个方向的选题&#xff0c;包括Jav…

linux RT-Preempt spin lock实现

一、spin_lock概述 Spinlock是linux内核中常用的一种互斥锁机制&#xff0c;和mutex不同&#xff0c;当无法持锁进入临界区的时候&#xff0c;当前执行线索不会阻塞&#xff0c;而是不断的自旋等待该锁释放。正因为如此&#xff0c;自旋锁也是可以用在中断上下文的。也正是因为…

Ubuntu 22.04 桥接配置

1. 网卡配置文件备份 sudo cp /etc/netplan/01-network-manager-all.yaml /etc/netplan/01-network-manager-all.yaml.bak 1.1 静态ip配置 1.1.3 解释 network: version: 2 ethernets: # 网卡名称 使用ifconfig查看 ens33: dhcp4: false dhcp6: false …

PHP多功能投票小程序源码

多功能投票小程序&#xff1a;全方位打造专属投票盛宴的得力助手 &#x1f389; &#x1f527; 基于先进的ThinkPHP框架与Uniapp技术深度融合&#xff0c;我们匠心独运&#xff0c;精心雕琢出一款功能全面、操作便捷的投票小程序&#xff0c;旨在为您带来前所未有的投票体验。…

[fastadmin] 第三十四篇 FastAdmin 商城模块标签使用详解

FastAdmin 商城模块标签使用详解 一、标签基本语法 1.1 基础语法格式 {shop:goodslist flag"参数值" id"变量名" row"数量"}<!-- 循环内容 --> {/shop:goodslist}1.2 常用参数说明 flag: 商品标记筛选id: 循环变量名row: 显示数量 1.…

二维数组-

定义&#xff1a;二维数组本质上也就是一维数组&#xff0c;只不过每个元素又是一个一维数组 基本语法&#xff1a; 数据类型[][] 数组名称 new 数据类型 [行数][列数] {}初始化数据; 示例&#xff1a; public class Test {public static void main(String[] args) {int[]…

软件测试预备知识④—NTFS权限管理、磁盘配额与文件共享

在软件测试的实际环境搭建与管理过程中&#xff0c;了解和掌握NTFS权限管理、磁盘配额以及文件共享等知识至关重要。这些功能不仅影响系统的安全性和稳定性&#xff0c;还对测试数据的存储、访问以及多用户协作测试有着深远的影响。 一、NTFS权限管理 1.1 NTFS简介 NTFS&am…

自动控制原理初识

文章目录 1.引言2.自动控制原理2.1方框图的案例2.2方框图里面的相关符号2.3闭环控制系统的特点2.4三种基础控制方式2.5对于控制系统的基本要求2.6自动控制原理的体系架构 3.控制系统的数学模型3.1为什么建模3.2建模的方法3.3什么是线性系统3.4线性or非线性系统判断3.5时变or定常…