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

【Rust 易学教程】第 1 天:Rust 基础,基本语法

上一节:【Rust 易学教程】学前准备:Cargo, 你好

今天,我们正式进入 Rust 基础的学习。在本文的内容中,我会为大家介绍以下内容:

  1. 基本 Rust 语法: 变量、标量和复合类型、枚举、结构、引用、函数和方法。
  2. 控制流结构: if、if let、while、while let、break 和 continue
  3. 模式匹配: 解构枚举、结构体和数组。

Rust 是个啥

Rust 是一种新的编程语言,在 2015 年发布了 1.0 版本,我会从以下方面让你知道 Rust 出现的意义:

  • Rust 是一种静态编译语言,其作用与 c++ 类似。rustc 使用 LLVM作为它的编译框架(关于 LLVM 的具体了解,可以访问其官方网址:https://llvm.org/)。
  • Rust 支持许多平台和架构。例如 x86, ARM, WebAssembly, …等架构,以及 Linux, Mac, Windows, …等平台。
  • Rust 被用于广泛的设备,如 固件和引导加载的启动程序、智能显示设备、移动电话、桌面、服务器等等。

我们发现,Rust 有与 c++ 相同的特性:

  • 高的灵活性。
  • 高度控制。
  • 可以缩小到非常受限的设备,如微控制器。
  • 没有运行时或垃圾收集。
  • 在不牺牲性能的前提下,注重可靠性和安全性。

Hi,I am Rust

了解了 Rust 是什么后,就让我们先来体验一番 Rust 最简单的程序:

fn main() {println!("Hi, I am Rust!");
}

从上面的代码中,我们看到 rust 代码具有如下一些特征:

  • 函数由 fn 引入。
  • 像 C 和 c++ 一样,块由花括号分隔。
  • main 函数是程序的入口点。
  • Rust 有卫生宏(hygienic macros),println! 就是它的一个例子。
  • Rust 字符串是 UTF-8 编码的,可以包含任何 Unicode 字符。

什么是 卫生宏?卫生宏和普通宏的区别有点类似词法作用域函数和动态作用域函数的区别。比如宏调用处有个名字 name1,同时宏内部也有一个名字 name1,那么卫生宏展开的时候就会把自己内部的 name1 改名成 name2;普通宏则不改名,“捕捉”外部的名字。

为了方便你理解,我在这里再小结一下上面的内容:

  1. Rust 非常像其他遵循 C/ c++ /Java 范式的传统语言。

  2. Rust 是现代的,完全支持 Unicode 之类的东西。

  3. Rust 在需要可变数量的参数(不允许函数重载)的情况下使用宏
    宏是“卫生的”,意味着它们不会意外地从它们所使用的范围中捕获标识符。Rust 宏实际上只是部分卫生的

  4. Rust 是多范式的。例如,它具有强大的面向对象编程特性,而且,虽然它不是函数式语言,但它包含了一系列函数式概念。

根据上面的小结,你是否也能发现 Rust 的一些独特卖点:

  • 编译时内存安全。例如,Rust 通过借用检查器消除了整个类的运行时错误,得到了像 C和 c++ 一样的性能,但没有内存不安全的问题。此外,还可以获得具有模式匹配和内置依赖项管理等结构的现代语言。
  • 缺少未定义的运行时行为。
  • 现代语言的特点。例如,可以获得像 C和c++ 那样快速且可预测的性能(没有垃圾收集器)以及访问低级硬件。

为什么是 Rust

接下来,我会为你从几个方面介绍为什么 Rust 会在众多语言中突出重围。先来一个示例。

示例:C 语言是怎么做的

首先,我们来看一个 C 语言的例子:

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>int main(int argc, char* argv[]) {char *buf, *filename;FILE *fp;size_t bytes, len;struct stat st;switch (argc) {case 1:printf("Too few arguments!\n");return 1;case 2:filename = argv[argc];stat(filename, &st);len = st.st_size;buf = (char*)malloc(len);if (!buf)printf("malloc failed!\n", len);return 1;fp = fopen(filename, "rb");bytes = fread(buf, 1, len, fp);if (bytes = st.st_size)printf("%s", buf);elseprintf("fread failed!\n");case 3:printf("Too many arguments!\n");return 1;}return 0;
}

上面的代码中,你发现了多少 bug?

尽管只有29行代码,但这个 C 语言示例中至少有 11 行包含了严重的错误:

  • 赋值=而不是相等比较==(第28行)
  • printf 的多余参数(第23行)
  • 文件描述符泄漏(在第26行之后)
  • 多行 if 中忘记使用大括号(第22行)
  • switch 语句中忘记了中断(第32行)
  • 忘记了 buf 字符串的 null 终止,导致缓冲区溢出(第29行)
  • 不释放 malloc 分配的缓冲区导致内存泄漏(第21行)
  • 越界访问(第17行)
  • 未检查 switch 语句中的情况(第11行)
  • 未检查statfopen 的返回值(第18行和第26行)

即使对于 C 编译器,这些错误也不应该很明显吗?
不,令人惊讶的是,即使在最新的GCC版本(撰写本文时为13.2)中,该代码也会在默认警告级别下编译无警告。

这不是一个非常不现实的例子吗?
绝对不是,这类错误在过去会导致严重的安全漏洞。例如:

  • 赋值=代替相等比较==: 2003年 Linux 后门尝试漏洞
  • 忘记在多行 if 中使用大括号: Apple的 goto fail 漏洞
  • switch 语句中被遗忘的中断: 中断 sudo 的中断

那么,你可能会问 Rust 在这里又能好到哪里去呢?
—— Safe Rust 使所有这些 bug 都不可能出现,例如以下:

  • 不支持if子句中的赋值。
  • 格式字符串在编译时进行检查。
  • 资源通过 Drop 特性在作用域结束时被释放。
  • 所有 if 子句都需要大括号。
  • match(在Rust中相当于switch) 不会失败,因此开发者不会不小心忘记了 break
  • 缓冲区切片携带它们的大小,不依赖于 NULL` 终止符。
  • 当相应的 Box 离开作用域时,通过 Drop 特性释放堆分配的内存。
  • 越界访问会导致 panic,或者可以通过切片的 get 方法进行检查。
  • match 会要求所有 case 都要得到处理。
  • 易出错的 Rust 函数返回的 Result 值需要拆封,从而检查是否成功。此外,如果没有检查带有 #[must_use]标记的函数的返回值,编译器会发出警告。

编译时验证

编译时的静态内存会进行如下验证:

  • 验证没有未初始化的变量。
  • 验证没有内存泄漏。
  • 验证没有 double-frees
  • 验证 use-after-free
  • 验证 NULL 指针。
  • 验证忘记锁定的互斥锁。
  • 验证线程之间没有数据竞争。
  • 验证迭代器是否失效。

运行时验证

以下行为将会判定为是在运行时无未定义的行为:

  • 检查数组访问的边界。
  • 定义了整数溢出(panic 或 wrap-around)。

整数溢出是通过编译时溢出检查标志定义的。如果启用,程序将陷入奔溃,否则开发者将获得环绕语义。默认情况下,将在调试模式(cargo build)和发布模式(cargo build --release)中获得 panic。

不能使用编译器标志禁用边界检查。它也不能直接使用不安全关键字禁用。但是,不安全允许开发者调用诸如slice::get_unchecked 之类的函数,这些函数不进行边界检查。

Rust 具备现代语言的特性

Rust 是用过去几十年积累的所有经验构建起来的,汲取几大语言的精华,又进行了改进。在语言特性上,它具备以下几点:

  • 枚举和模式匹配。
  • 泛型。
  • 没有额外的 FFI
  • 零成本抽象。

在工具支持上,具备以下几点:

  • 良好的编译器错误检测。
  • 内置依赖项管理器。
  • 内置测试的支持。
  • 优秀的语言服务器协议支持。

往更细的说,主要是以下几点:

  • 零成本抽象,类似于c++,意味着你不必为使用内存或 CPU 的高级编程结构“付费”。例如,使用 For 编写循环应该产生与使用.iter().fold() 结构大致相同的低级指令。

  • 值得一提的是,Rust 枚举是“代数数据类型”,也被称为“和类型”,它允许类型系统表达像Option<T>和Result<T, E>这样的东西。

  • 提醒开发者关注错误——许多开发者已经习惯忽略冗长的编译器输出。Rust 编译器明显比其他编译器更健谈。它通常会为开发者提供可操作的反馈,准备复制粘贴到你的代码中。

  • 与Java、Python和Go等语言相比,Rust 标准库很小。Rust 没有提供一些你可能认为是标准和必要的东西,例如:

    • 一个随机数生成器,但开发者请参阅 rand。
    • 支持SSL或TLS,但开发者请参阅 rusttls。
    • 对JSON的支持,开发者可以参阅 serde_json。这背后的原因是标准库中的功能不能消失,所以它必须非常稳定。对于上面的例子,Rust 社区仍在努力寻找最佳解决方案——也许对于其中的一些事情没有单一的“最佳解决方案”。

Rust 附带了 Cargo 形式的内置包管理器,这使得下载和编译第三方 crate 变得非常简单。这样做的结果是标准库可以更小。https://lib.rs 这个网站可以帮助你找到更多第三方库。

  • rust-analyzer 对主要的 ide 和文本编辑器实现了支持。

基础语法

大部分 Rust 语法对于 C、c++或Java 来说都很熟悉。例如:

  • 块和作用域由花括号分隔。
  • 行注释以//开头,块注释以/*…* /
  • ifwhile这样的关键词的工作原理是一样的。
  • 变量赋值用=完成,比较用==完成。

标量类型

类型示例
有符号整数i8, i16, i32, i64, i128, isize-10, 0, 1_000, 123_i64
无符号整数u8, u16, u32, u64, u128, usize0, 123, 10_u16
浮点数f32, f643.14, -10.0e20, 2_f32
字符串&str“foo”, “two\nlines”
Unicode标量值char‘a’, ‘α’, ‘∞’
布尔型booltrue, false

上方表格中,数字中的所有下划线都可以省略,它们只是为了便于阅读。因此,1_000可以写成1000(或10_00)123_i64可以写成123i64

同时,上面的类型的宽度如下:

  • iN, uN 和 fN 是 N 位宽,
  • Isize 和 usize是指针的宽度,
  • Char 是 32 位宽,
  • Bool 是 8 位宽。

除此之外,原始字符串允许开发者创建一个转义值,如: r"\n" == "\\n"。你可以嵌入双引号,在引号的两边加上等量的#:

fn main() {println!(r#"<a href="link.html">link</a>"#);println!("<a href=\"link.html\">link</a>");
}

字节(Byte)字符串允许你直接创建&[u8]值:

fn main() {println!("{:?}", b"abc");println!("{:?}", &[97, 98, 99]);
}

复合类型

类型示例
数组[T; N][20, 30, 40], [0; 3]
元组(), (T,), (T1, T2), …(), (‘x’,), (‘x’, 1.2), …

数组的赋值和访问:

fn main() {let mut a: [i8; 10] = [42; 10];a[5] = 0;println!("a: {a:?}");
}
  • 数组类型 [T;N] 保存了 N 个(编译时常量)相同类型 t 的元素。注意,数组的长度是其类型的一部分,这意味着 [u8;3][u8;4] 被认为是两种不同的类型。
  • 可以使用字面量给数组赋值。
  • 添加 #,例如{a:#?},可以有“漂亮的输出”格式,这样更容易阅读。

元组的赋值和访问:

fn main() {let t: (i8, bool) = (7, true);println!("t.0: {}", t.0);println!("t.1: {}", t.1);
}
  • 与数组一样,元组也有固定的长度。

  • 元组将不同类型的值组合成一个复合类型。

  • 元组的字段可以通过周期和值的索引来访问,例如 t.0, t.1

  • 空元组 () 也被称为“单元类型”。它既是一个类型,又是该类型的唯一有效值——也就是说,该类型及其值都表示为 ()。例如,它用于表示函数或表达式时没有返回值。

引用类型

和c++一样,Rust 也有引用类型:

fn main() {let mut x: i32 = 10;let ref_x: &mut i32 = &mut x;*ref_x = 20;println!("x: {x}");
}

需要注意的是:

  • 赋值时必须解除对 ref_x 的引用,类似于 C 和 c++ 指针。
  • Rust 在某些情况下会自动解除引用,特别是在调用方法时(如, ref_x.count_ones())。
  • 声明为 mut 的引用可以在其生命周期内绑定到不同的值。
  • 一定要注意 let mut ref_x: &i32let ref_x: &mut i32 之间的区别。第一个表示可以绑定到不同值的可变引用,而第二个表示对可变值的引用。
悬垂引用

Rust 将静态地禁止悬垂引用:

fn main() {let ref_x: &i32;{let x: i32 = 10;ref_x = &x;}println!("ref_x: {ref_x}");
}
  • 引用,你可以想象为为“借用”它所引用的值。
  • Rust 正在跟踪所有引用的生命周期,以确保它们活得足够长。

Slices 切片

切片为开发者提供了更大集合的视图:

fn main() {let mut a: [i32; 6] = [10, 20, 30, 40, 50, 60];println!("a: {a:?}");let s: &[i32] = &a[2..4];println!("s: {s:?}");
}

上述代码中,我们通过借用 a 并在括号中指定起始和结束索引来创建切片。

  • 如果切片从索引0开始,Rust的范围语法允许我们删除起始索引,这意味着&a[0.. .len()]&a[.. .. len()]是相同的。

  • 对于最后一个索引也是如此,所以a &a[2.. .len()]a &a[2..]都是一样的。

因此,为了方便地创建整个数组的切片,我们可以使用&a[…]

S是对i32s切片的引用。注意,s (&[i32])的类型不再提到数组长度。这允许我们对不同大小的切片执行计算。

切片总是从另一个对象借用。在本例中,a 必须保持“活动”(在作用域中)至少与我们的切片一样长。

String Vs Str

现在我们可以理解Rust中的两种字符串类型:

fn main() {let s1: &str = "World";println!("s1: {s1}");let mut s2: String = String::from("Hello ");println!("s2: {s2}");s2.push_str(s1);println!("s2: {s2}");let s3: &str = &s2[6..];println!("s3: {s3}");
}
  • &str: 对字符串切片的不可变引用

  • String: 可变字符串缓冲区

  • &str 引入了一个字符串切片,它是对存储在内存块中的UTF-8编码字符串数据的不可变引用。字符串字面值(" Hello ")存储在程序的二进制文件中。

  • Rust 的 String 类型是一个字节向量的包装器。与Vec<T>一样,它是私有的。

  • 与许多其他类型一样,String::from() 从字符串字面值创建字符串。String::new() 创建一个新的空字符串,可以使用push()push_str()方法向其添加字符串数据。

  • 宏是一种从动态值生成私有字符串的方便方法。它接受与 println!() 相同的格式规范。

  • 你可以通过 &和可选的范围选择从 String 中借用 &str 切片。

  • 对于c++程序员: 你可以将 &str 看作 c++ 中的 const char*,但它总是指向内存中的有效字符串。Rust String 大致相当于c++中的std:: String(主要区别:它只能包含UTF-8编码的字节,并且永远不会使用小字符串优化)。

Functions

Methods

方法是与类型相关联的函数。方法的self参数是它所关联类型的一个实例:

struct Rectangle {width: u32,height: u32,
}impl Rectangle {fn area(&self) -> u32 {self.width * self.height}fn inc_width(&mut self, delta: u32) {self.width += delta;}
}fn main() {let mut rect = Rectangle { width: 10, height: 5 };println!("old area: {}", rect.area());rect.inc_width(5);println!("new area: {}", rect.area());
}
  • 添加一个名为Rectangle::new的静态方法,并从 main 调用它:
fn new(width: u32, height: u32) -> Rectangle {Rectangle { width, height }
}
  • 虽然从技术上讲,Rust没有自定义构造函数,但静态方法通常用于初始化结构。实际的构造函数Rectangle {width, height}可以直接调用。

  • 添加 Rectangle::square(width: u32) 构造函数来说明此类静态方法可以接受任意参数。

函数重载

不支持重载:

  • 每个函数有一个单独的实现:

    • 总是有固定数量的参数。
    • 总是接受一组参数类型。
  • 不支持默认值:

    • 所有调用站点都具有相同数量的参数。
    • 有时使用宏作为替代方法。

然而,函数参数可以是泛型的:

fn pick_one<T>(a: T, b: T) -> T {if std::process::id() % 2 == 0 { a } else { b }
}fn main() {println!("coin toss: {}", pick_one("heads", "tails"));println!("cash prize: {}", pick_one(500, 1000));
}

当使用泛型时,标准库的Into可以在参数类型上提供一种有限的多态性。这一点我将在后面的小节中介绍更多细节。

相关文章:

【Rust 易学教程】第 1 天:Rust 基础,基本语法

上一节&#xff1a;【Rust 易学教程】学前准备&#xff1a;Cargo&#xff0c; 你好 今天&#xff0c;我们正式进入 Rust 基础的学习。在本文的内容中&#xff0c;我会为大家介绍以下内容&#xff1a; 基本 Rust 语法: 变量、标量和复合类型、枚举、结构、引用、函数和方法。控…...

Linux(命令)——结合实际场景的命令 查找Java安装位置命令

前言 在内卷的时代&#xff0c;作为开发的程序员也需要懂一些Linux相关命令。 本篇博客结合实际应用常见&#xff0c;记录Linux命令相关的使用&#xff0c;持续更新&#xff0c;希望对你有帮助。 目录 前言引出一、查找Java安装位置命令1、使用which命令2、使用find命令3、查…...

C语言基础 -- scanf函数的返回值及其应用

前言、scanf函数有返回值 我们在作PTA上的编程作业时&#xff0c;经常在编译窗口会看到如下的信息&#xff1a; warning: ignoring return value of ‘scanf’, declared with attribute warn_unused_result [-Wunused-result] 当时老师一定会告诉你&#xff0c;这个一个&qu…...

mac 安装 selenium + chrome driver

前言 使用 selenium 模拟浏览器渲染数据&#xff0c;需要依赖各浏览器的驱动才能完成&#xff0c;因此需要单独安装chrome driver 查看本地 chrome 浏览器的版本 可以看到我这里已经是 arm 架构下最新的版本了 下载对应的 chrome driver 访问下面的地址&#xff1a; Chrome…...

【阿里云】函数计算 X 通义千问快速部署

写在前面&#xff1a;博主是一只经过实战开发历练后投身培训事业的“小山猪”&#xff0c;昵称取自动画片《狮子王》中的“彭彭”&#xff0c;总是以乐观、积极的心态对待周边的事物。本人的技术路线从Java全栈工程师一路奔向大数据开发、数据挖掘领域&#xff0c;如今终有小成…...

el-table本地与线上的样式不一致出现错乱

使用el-table的时候有几个表头是循环出来的&#xff0c;出现在本地运行的时候&#xff0c;表头内el-input输入框样式正常&#xff0c;但是发布以后出现样式错乱问题 线上样式错乱&#xff1a;​ 本地正常&#xff1a; 出现这个问题的原因是我有几个表头是循环出来的&#xff0…...

C语言--从键盘输入当月利润I,求应发奖金总数。

题目描述&#xff1a; 企业发放的奖金根据利润提成。利润I低于或等于100000元的&#xff0c;奖金可提成10%; 利润高于100000 元&#xff0c;低于200000元(1000001000000时&#xff0c;超过1000000元的部分按 1%提成。从键盘输入当月利润I,求应发奖金总数。 int main() {int m…...

记忆科技携手中国电信,一站式存储打造坚实数字底座

11月10日&#xff0c;以“数字科技 焕新启航”为主题的2023数字科技生态大会在广州盛大开幕&#xff0c;本次大会由中国电信、广东省人民政府联合举办&#xff0c;是一场数字科技领域的年度盛会。忆联母公司记忆科技作为中国电信的合作伙伴之一受邀参会&#xff0c;深度参与了大…...

基于ssm的学生档案管理系统(有报告)。Javaee项目,ssm项目。

演示视频&#xff1a; 基于ssm的学生档案管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;ssm项目。 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 项目介绍&#xff…...

阿里云服务中断事件:原因、影响与解决方案

&#x1f495;欢迎大家&#xff1a;这里是CSDN&#xff0c;我总结知识的地方&#xff0c;欢迎来到我的博客&#xff0c;感谢大家的观看&#x1f970; 如果文章有什么需要改进的地方还请大佬不吝赐教 先在次感谢啦&#x1f60a; 文章目录 阿里云服务中断事件&#xff1a;原因、影…...

搜维尔科技:「体育类」Movella Xsens极限运动捕捉测试

搜维尔科技&#xff1a;「体育类」Movella Xsens极限运动捕捉测试...

CSS常用示例100+ 【目录】

目前已有文章 11 篇 本专栏记录的是经常使用的CSS示例与技巧&#xff0c;主要包含CSS布局&#xff0c;CSS特效&#xff0c;CSS花边信息三部分内容。其中CSS布局主要是列出一些常用的CSS布局信息点&#xff0c;CSS特效主要是一些动画示例&#xff0c;CSS花边是描述了一些CSS相关…...

Shopee买家通系统之注册虾皮买家号大概需要多少成本

想要注册大量的虾皮买家号&#xff0c;可以使用shopee买家通系统进行注册&#xff0c;这款软件可以全自动化的注册虾皮买家号&#xff0c;不过想要自动化更方便&#xff0c;对于账号资料有一定的要求。 1、现在注册虾皮买家号基本上都是需要用手机号注册了的&#xff0c;而虾皮…...

华为层层“能力外溢”,让数智世界一触即达——选择华为,让您的企业轻松数智化

作者 | 曾响铃 文 | 响铃说 7万多人现场观赛&#xff0c;手机信号不掉链子&#xff0c;能发图片视频、能分享朋友圈&#xff1b; 消防、闸机等多个安防系统联动&#xff0c;风险事件自动报告&#xff0c;观赛、办赛安心&#xff1b; 运营数据全面打通、实时更新&#xff0c…...

MHA实验和架构

什么是MHA&#xff1f; masterhight availabulity&#xff1a;基于主库的高可用环境下可以实现主从复制、故障切换 MHA的主从架构最少要一主两从 MHA的出现是为了解决MySQL的单点故障问题。一旦主库崩溃&#xff0c;MHA可以在0-30秒内自动完成故障切换。 MHA的数据流向和工…...

C语言——函数

导读 &#xff1a; 这篇文章主要讲解一下C语言函数的一些基本知识。 前言&#xff1a;函数的概念 C语言中的函数又常常被称为子程序&#xff0c;是用来完成某项特定的工作的一段代码。就像我们生活中的模块化建造技术&#xff0c;类比模块化建房子的过程&#xff1a;整个程序…...

DDR SDRAM 学习笔记

一、基本知识 1.SDRAM SDRAM : 即同步动态随机存储器&#xff08;Synchronous Dynamic Random Access Memory&#xff09;, 同步是指其时钟频率与对应控制器&#xff08;CPU/FPGA&#xff09;的系统时钟频率相同&#xff0c;并且内部命令 的发送与数据传输都是以该时钟为基准…...

RocketMQ(4.9.4)学习笔记 - 安装部署

单机部署&#xff1a; 官网文档地址&#xff1a; https://rocketmq.apache.org/zh/docs/4.x 参考文档&#xff1a; windows安装RocketMQ_rocketmq windows_book多得的博客-CSDN博客 下载地址&#xff1a; https://archive.apache.org/dist/rocketmq/4.9.4/rocketmq-all-4.9.…...

虚拟局域网

虚拟局域网(VLAN) VLAN建立于交换技术的基础之上 广播域(broadcast domain)&#xff1a;其中任何一台设备发出的广播通信都能被该部分网络中的所有其他设备所接收&#xff0c;这部分网络就叫广播域利用以太网交换机可以很方便地实现虚拟局域网VLAN(Virtual LAN)对于一个主机和…...

【PG】PostgreSQL 预写日志(WAL)、checkpoint、LSN

目录 预写式日志&#xff08;WAL&#xff09; WAL概念 WAL的作用 WAL日志存放路径 WAL日志文件数量 WAL日志文件存储形式 WAL日志文件命名 WAL内容 检查点&#xff08;checkpoint&#xff09; 1 检查点概念 2 检查点作用 触发检查点 触发检查点之后数据库操作 设置合…...

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…...

Java 语言特性(面试系列1)

一、面向对象编程 1. 封装&#xff08;Encapsulation&#xff09; 定义&#xff1a;将数据&#xff08;属性&#xff09;和操作数据的方法绑定在一起&#xff0c;通过访问控制符&#xff08;private、protected、public&#xff09;隐藏内部实现细节。示例&#xff1a; public …...

在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能

下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能&#xff0c;包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

IGP(Interior Gateway Protocol,内部网关协议)

IGP&#xff08;Interior Gateway Protocol&#xff0c;内部网关协议&#xff09; 是一种用于在一个自治系统&#xff08;AS&#xff09;内部传递路由信息的路由协议&#xff0c;主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

Qt Widget类解析与代码注释

#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码&#xff0c;写上注释 当然可以&#xff01;这段代码是 Qt …...

汽车生产虚拟实训中的技能提升与生产优化​

在制造业蓬勃发展的大背景下&#xff0c;虚拟教学实训宛如一颗璀璨的新星&#xff0c;正发挥着不可或缺且日益凸显的关键作用&#xff0c;源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例&#xff0c;汽车生产线上各类…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序

一、开发准备 ​​环境搭建​​&#xff1a; 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 ​​项目创建​​&#xff1a; File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业

6月9日&#xff0c;国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解&#xff0c;“超级…...

12.找到字符串中所有字母异位词

&#x1f9e0; 题目解析 题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义&#xff1a; 若两个字符串包含的字符种类和出现次数完全相同&#xff0c;顺序无所谓&#xff0c;则互为…...