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

网站策划方法乐华网络公司服务内容

网站策划方法,乐华网络公司服务内容,国外设计师作品网站,外贸网站怎样注册清理特型Drop 当一个值的拥有者消失时#xff0c;Rust 会丢弃#xff08;drop#xff09;该值。丢弃一个值就必须释放 该值拥有的任何其他值、堆存储和系统资源。 丢弃可能发生在多种情况下#xff1a; 当变量超出作用域时#xff1b;在表达式语句的末尾#xff1b;当…清理特型Drop 当一个值的拥有者消失时Rust 会丢弃drop该值。丢弃一个值就必须释放 该值拥有的任何其他值、堆存储和系统资源。 丢弃可能发生在多种情况下 当变量超出作用域时在表达式语句的末尾当截断一个向量时会从其末尾移除元素 struct Appellation {name: String,nicknames: VecString }每当 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_sizeT: ?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]、Boxdyn Trait来间接引用。 使用场景 泛型编程当你编写泛型代码时默认情况下你的泛型参数是 Sized 的。如果你想让泛型参数接受动态大小类型你需要显式地指定 ?Sized。 特质对象当你创建特质对象如 Boxdyn Trait 或 dyn Trait时特质本身并不实现 Sized因为特质对象的实际大小是在运行时决定的。 结构体和枚举如果结构体或枚举包含字段或变体这些字段或变体必须是 Sized 的除非你使用了特殊的语法如裸指针来处理动态大小类型。 示例代码 下面是一个简单的例子展示了 Sized 和 ?Sized 的使用 // 这个函数只接受具有已知大小的类型 fn only_sizedT: Sized(t: T) {// 函数体... }// 这个函数可以接受任何类型包括动态大小类型 fn also_unsizedT: ?Sized(t: T) {// 函数体... }struct WrapperT: ?Sized {value: BoxT, }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 结构体能够包含动态大小类型因为它使用了 BoxT 来间接持有数据。 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 ST { ... }那么 Rust 会将其理解为 struct ST:Sized { ... }。如果你不想以这种方式约束 T就必须将 其明确地排除写成 struct ST:?Sized { ... }。?Sized 语法专用 于这种情况意思是“不要求固定大小的”。如果你写 struct S T: ?Sized{ b: Box }那么 Rust 将允许写成 Sstr 和 Sdyn Write这样这 两个 Box 就变成了胖指针而不像 Si32 和 SString 的 Box 那样只是普通指针。 尽管存在一些限制但无固定大小类型能让 Rust 的类型系统工作得更顺畅。偶尔会遇到类型变量上的 ?Sized 限界这几乎总是表明 “给定的类型只能通过指针访问”并能让其关联的代码与切片对象和特型对象以及普通值一起使用。当类型变量具有?Sized限界时它的大小不确定既可能是固定大小也可能不是。 【柔性数组】除了切片对象和特型对象还有另一种无固定大小类型。结构体类型的最后一个字段而且只能是最后一个可以是无固定大小的并且这样的结构体本身也是 无固定大小的。例如Rc 引用计数指针的内部实现是指向私有类型 RcBox 的指针后者把引用计数和 T 保存在一起。下面是 RcBox 的简化定义 struct RcBoxT: ?Sized {ref_count: usize, value: T, }Rc T是引用计数指针其中的 value 字段是 Rc T对其进行引用计数的 T 类型。RcT 会解引用成指向 value 字段的指针。ref_count 字段会保存其 引用计数。 真正的 RcBox 只是标准库的一个实现细节无法在外部使用。但假设我们正在使用前面这种定义那么就可以将此 RcBox 与固定大小类型一起使用比如 RcBox String的结果是一个固定大小的结构体类型。 或者也可以将它与无固 定大小类型一起使用比如 RcBoxdyn Display 就成了无固定大小的结构体类型。 不能直接构建 RcBoxdyn Display 值而应该先创建一个普通的固定大小 的 RcBox并让其 value 类型实现 Display比如 RcBoxString。然后 Rust 就会允许你将引用 RcBox String转换为胖引用 RcBoxdyn Display let boxed_lunch: RcBoxString RcBox {ref_count: 1,value: lunch.to_string() }; use std::fmt::Display; let boxed_displayable: RcBoxdyn Display boxed_lunch;将值传给函数时会发生隐式转换可以将 RcBox 传给需 要 RcBox 的函数 fn display(boxed: RcBoxdyn 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 等原始 类型实现了 CloneString、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.tj-hxxt.cn/news/225938.html

相关文章:

  • 网站开发工程师工资hangq个性定制网站
  • 中国建设网站的证件怎么查询php 双下划线 wordpress
  • 专门做母婴的网站有哪些asp net网站开发
  • 南京产品网站建设收费做网站找哪家好 07月
  • 单页网站制作系统苏州seo报价
  • 上海浦东网站建设公司手机网站 方案
  • 网站建设最流行语言wordpress下载面板样式
  • 做网站页面的视频电子商务网站建设管理论文
  • 网站建设需要注意哪些方面潍坊外贸网站建设
  • 最好的网站建设组织代理公司英文
  • 个人网站做支付接口网站公司用什么软件做网站
  • 怎么给网站制作二维码聊城市住房和城乡建设局网站
  • 网站建设属于什么行业分类郑州网站建设企业名录
  • 网站建设菜鸟教程如何做新网站保留域名
  • 长沙网站优化诊断特效网站
  • 湖州医院网站建设方案青海省电话黄页
  • 北京的电商平台网站有哪些平台网站
  • 团购网站怎么做推广dw做网站链接数据库
  • 做网页代码的素材网站培训机构网站制作
  • 怎么把网站做10万ipwordpress主题制作主题选项
  • 网站建设添加视频小红书推广方法
  • 安庆哪里做网站微信表情开放平台官网
  • 重庆建筑信息工程官网深圳网站seo外包公司哪家好
  • 没有空间可以做网站吗怎么建设回收网站
  • 全屏响应式网站模板长沙网站建站
  • 外贸网站优化方案企业网站管理系统用哪个好
  • 雄安网站建设机构室内设计公司办公室图片
  • 做百度竞价什么网站好互联网门户网站模板
  • 网站源码大全免费的营销网站的优势是什么意思
  • 屏山县建设局网站做网站ui去哪儿接私活