Rust 变量和基础类型

news/2024/10/11 15:12:37

通过 let 关键字声明变量, 变量默认是不可变 (只读) 的.

let foo = 5; // 创建了一个不可变的变量 foo, 并绑定了 5
foo = 10; // 不能对 foo 重新绑定// 使用 mut 关键字创建可变的
let mut bar = 5;
bar = 10; // 可以重新绑定

不需要写变量类型, 编译器可以自己推导, 但是常量 (const) 和静态变量 (static) 必须声明类型.

也可以使用相同的名字声明新的变量, 新的变量就会隐藏之前的声明的同名变量.

let x = 1;
// 第二次声明的 x 可以和第一次声明的 x 类型不一样.
let x = "";

常量

使用 const 关键字声明常量.

它和变量的区别:

  • 不能使用 mut 关键字, 常量必须是不可变的.

  • 常量必须指定类型.

  • 常量可以在任何作用域内进行声明, 包括全局作用域.

  • 常量只可以绑定到常量表达式, 无法绑定到函数的调用结果或只能在运行时才能计算出的值.

    比如: 10*10 就是常量表达式, 10*i 就是通过运行时才能计算.

    但是有另外一种情况, 如果 i 也是常量, 那么就没问题.

const MAX_POINTS: u32 = 100_000; // 使用下划线是为了提高可读性.
// 在代码中使用了 MAX_POINTS 常量, 在编译的时候会直接替换为实际值 100_000.

静态变量

静态变量的语法和常量的语法相似, 只不过静态变量可以使用 mut 关键字.

static HELLO: &str = "Hello, world!";

静态变量的生命周期和整个程序的生命周期一样.

数据类型

栈上保存的是固定大小类型的值, 比如指针, u8, char 类型等, 这些类型都是固定大小的.

堆上保存的是非固定大小类型的值, 这些值在使用的时候会动态调整大小.

Rust 不支持隐式类型转换, 比如不会自动将 16 位整数转换为 32 位整数.

数字类型

分组 说明
i8, i16, i32, i64, i128 有符号整数类型, 范围是 8 位到 64 位.
u8, u16, u32, u64, u128 无符号整数类型, 范围是 8 位到 64 位.
f32, f64 浮点数类型, 有 32 位和 64 位两种.
isize, usize 在 64 位 CPU 上, isize 和 usize 都是 64 位.

虽然都是数字类型, 但是不同的数字类型不能比较.

比如 i16 > u16 不能比较, i16 > i32 也不能比较, 但是可以通过 std::convert::TryFrom 进行转换.

元组 (Tuple)

元组的长度是固定的, 一旦声明就无法改变, 但是每一个元素都可以是不同的类型.

let tup:(i32, f64, u8) = (500, 6.4, 1);// 不能使用 tup[0], 也不能使用变量 tup.(1-1).
println!("{}, {}, {}", tup.0, tup.1, tup.2);// 第二种使用方式, 叫做元组的析构.
let (x, y, z) = tup;
println!("{}, {}, {}", x, y, z);

() 是什么意思

  • 单元类型: 类似于其它编程语言中的 void.

  • 占位符: 在使用 Result<T, E> 类型时, 如果你只关心错误情况, 而成功情况不返回任何有意义的值, 你可以使用 () 作为 Ok 类型的值.

  • 空元组

数组

数组长度也是固定的, 一旦声明就无法改变, 而且每一个元素的类型必须相同.

数组的大小也是类型的一部分, 比如 [i32; 5][i32; 6] 是两个类型.

// 创建了一个长度为 5, 类型为 i32 的数组.
let a = [1, 2, 3, 4, 5];// 创建了一个长度为 5, 类型为 i32 的数组,
// 但是数组中的元素都是 3.
let a = [3; 5];// 这是错误的, 数组长度不能是变量.
// let a = [3; i];

切片

[T] 它就是一个切片类型, 表示一个动态大小的视图.

它只是对数据进行引用, 并不会复制数据或拥有数据的所有权.

动态大小是什么意思?

先来说一下静态大小, 比如说数组就是一个静态大小的, 因为数组在创建的时候就需要指定数组的大小.

然后动态大小就是反过来的, 就是说在创建的时候不需要指定大小, 而是在运行的时候才去确定大小.

不能直接使用切片类型, 因为编译器在编译的时候, 必须知道类型的大小.

你可能会想 t[0..3] 是用来创建切片的, 那么不是已经知道了切片的长度吗?

对, 确实可以在编译时推断出切片的长度, 但是编译器在处理切片的时候, 还是按照动态大小类型处理的.

let t = [3; 10];
// let t1: [i32] = t[0..3]; // 不能直接使用切片// t[0..3] 创建切片, 然后获取这个切片的不可变引用.
let t1: &[i32] = &t[0..3];

下面是切片的使用:

let array = [1, 2, 3, 4, 5];// 通过现有的数组创建出来一个切片,
// &[开始索引..结束索引],包头不包尾.
// &[开始索引..=结束索引],包头包尾.
//
// 还有一些简化方式:
// &[..结束索引]
// &[开始索引..]
// &[..]
&array[1..4]

可以对一个切片, 再进行切片.

下图比较清晰地呈现了切片和数据之间的关系:

下图比较清晰地呈现了切片和数据之间的关系.jpg

切片可以是可变的, 也可以是不可变的, 而且还可以通过 Box<[T]>, 在堆上分配切片.

切片文档: https://doc.rust-lang.org/std/primitive.slice.html

下图描述了数组、Vec<T>、切片引用 &[T]&mut [T], 以及在堆上分配的切片 Box<[T]> 之间的关系.

切片数组相互转换.jpg

Vec

Vector 是数组实现的, 适用于随机访问和频繁在尾部插入元素.

创建 Vector:

let my_vector: Vec<i32> = Vec::new();// 类型 i32.
let my_vector = vec![1, 2, 3];// 保存 u8 类型, 长度是 10, 默认值是 0.
let my_vector = vec![0u8; 10];

Vector 中的所有元素都是保存在堆内存中的, 比如上面的元素 1, 2, 3 也是保存在堆内存中的.

还有两个常用类型:

  • VecDeque: 是一个双端队列, 适用于在两端频繁添加和移除元素.

  • LinkedList: 是一个双向链表, 适用于在任意位置频繁插入和删除元素, 但不需要高效随机访问的场景.

HashMap

键值对的形式存储数据, 一个键 (Key) 对应一个值 (Value).

use std::collections::HashMap;let mut my_hashmap: HashMap<String, i32> = HashMap::new();

HashMap 中的所有元素都是保存在堆内存中的.

还有两个常用类型:
  • BTreeMap: 通过 B 树数据结构实现的有序键值对集合.
  • BTreeSet: 和 BTreeMap 类似, 只不过它的 key 不能重复.

如何解决冲突?

使用开放寻址法的二次探查来解决.

Rust-二次探查.jpg

要向 HashMap 中插入 e:5 数据, 通过 key: e 计算出来的 Hash 值, 是要将数据放在数组的 03 下标中.

但是 03 下标已经有数据了, 所以通过公式 hash(key)+N^2 计算下一个下标.

上面公式中的 N 是步长, 下标 03 中存放数据, 通过步长 1 找到下一个下标 04, 它也有数据所以步长加 1, 然后找到 07 下标.

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

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

相关文章

通义灵码 AI 程序员来了!丨阿里云云原生 9 月产品月报

《阿里云云原生每月动态》,从趋势热点、产品新功能、服务客户、开源与开发者动态等方面,为企业提供数字化的路径与指南。云原生月度动态 云原生是企业数字创新的最短路径。 《阿里云云原生每月动态》,从趋势热点、产品新功能、服务客户、开源与开发者动态等方面,为企业提供…

(python笔记)pandas 读取excel,如何保留文本数字类型

pandas读取Excel,默认转换文本类型数字为int类型,破坏原数据类型,用converters处理,保留文本类型数字 converters: dict[str, Callable] | dict[int, Callable] | None = ..., 使用方法:df = pd.read_excel(r"D:\测试文档\xxxx.xlsx", converters={"专业代…

蔡司库位架如何校准操作介绍

http://www.saben.com.cn/Article/cskwjrhxzc.html

三坐标探头种类及接针规则说明

http://www.saben.com.cn/Article/szbttzljjz.html

史陶比尔Stabli机器人维修小细节

在工业自动化领域,史陶比尔机器人以其卓越的性能和可靠性而著称。然而,即使是尖端的设备,也难免会遇到Stabli机械手故障和问题。对于机器人维护和修理,每一个小细节都显得至关重要。 一、观察 首先,我们需要具备敏锐的观察力。当史陶比尔机器人出现故障时,它可能会通过一…

23k star,推荐一款超强的开源工具--trivy

今天一件一款开源的镜像扫描工具,下面是扫描某个python镜像的示例:Trivy:全面的安全扫描工具 软件简介Trivy 是由 Aqua Security 开发的开源安全扫描工具,旨在帮助开发者和运维人员识别和修复各种环境中的安全问题。 Trivy 的名字来源于“Trigger”和“Envy”的组合,寓意其…

阿里云轻量服务器新版本frp配置【toml】

官网下载frp [ https://github.com/fatedier/frp/releases ] 1.frps配置(服务端) 解压tar -zxvf frp_0.60.0_linux_amd64.tar.gz进入该目录cd frp_0.60.0_linux_amd64编辑frps.tomlvim frps.toml往里面写入# frps.toml bindPort = 7000 # 服务端与客户端通信端口 …

Apache Solr8安装启动

目录1、使用root用户权限,创建名为solr的新用户,用于运行SOLR服务。2、使用root用户权限,将solr安装目录授权给solr用户3、从root用户切换到solr用户4、进入/opt/solr-8.11.4/bin目录,启动服务5、如果启动出现如下警告,若如下配置5.1、修改/etc/security/limits.conf文件5…