学习笔记三—— Rust 的数据类型

📚 目录导航

  1. 什么是 Rust 的类型系统?
  2. 标量类型(整数、浮点、布尔、字符)
  3. 复合类型(元组、数组)
  4. 字符串类型:&strString
  5. 自定义类型(结构体和枚举)
  6. 零大小类型(ZST):不占空间却意义重大
  7. _ 占位写法:只关心类型不关心名字
  8. 底类型 !:不会返回的类型到底有什么用?
  9. 总结 + 类型速查表

1️⃣ 什么是 Rust 的类型系统?

Rust 是一门:

  • 静态类型语言:变量类型在编译时就必须确定。
  • 强类型语言:类型不允许自动转换。
let x = 10;      // 推导为 i32
let y: u8 = x;   // ❌ 错误:不能自动转换
let y: u8 = x as u8; // ✅ 正确方式

这样的设计让程序在“还没跑起来”就发现 bug,提高了可靠性和安全性。


2️⃣ 标量类型:最基本的类型单位

类型示例说明
整数let a: i32 = 42;默认类型是 i32
浮点数let b = 3.14;默认类型是 f64
布尔值let f = true;只能是 true 或 false
字符let c = '🚀';单个 Unicode 字符

3️⃣ 复合类型:多个值组合成一个

✅ 元组 tuple

let info = ("Tom", 18, true);
let (name, age, active) = info;

✅ 数组 array

let scores = [90, 80, 70];
let first = scores[0];

数组长度固定,元素类型必须一致。


4️⃣ 字符串类型:&str 与 String 的区别

类型可变分配位置示例类比
&str栈/静态区"Tom"公告栏只读纸条
String堆上String::from("Tom")自己的记事本
let a = "Tom";                     // &str
let b = String::from("Tom");       // String,可变

5️⃣ 自定义类型:结构体和枚举

✅ 结构体 struct

struct User {
    name: String,
    age: u8,
}

✅ 枚举 enum

enum State {
    Loading,
    Success(String),
    Error(String),
}

6️⃣ 零大小类型(ZST):不占空间却意义重大

❓ 什么是 ZST?

ZST(Zero-Sized Type)就是占用内存为 0 字节的类型。

use std::mem::size_of;
println!("{}", size_of::<()>()); // 输出:0

✅ 常见 ZST 类型与用途

类型示例用途
单元类型()没有返回值或表示“空”
空数组[u8; 0]表示空集合,不占内存
空结构体struct Marker;类型标记,泛型占位
空元组结构体struct Wrapper();同上
PhantomData<T>PhantomData::<u32>声明与某类型有关,不持有它

🧠 为什么有 ZST 这种设计?

虽然它们不占空间,但可以在“类型层面”起作用:

  1. 编译期进行类型区分(比如泛型中标记数据类型)。
  2. 触发行为但不带数据(比如用 Marker 调用函数)。
  3. 用于实现某些 trait 的结构不需要状态

✅ 例子 1:类型标记

struct Marker;

fn init(_: Marker) {
    println!("执行初始化操作");
}

init(Marker); // ✅ Marker 不占空间但可以控制逻辑分支

✅ 例子 2:PhantomData 用法详解

use std::marker::PhantomData;

struct MyVec<T> {
    _marker: PhantomData<T>, // 虽然不存 T,但逻辑上依赖 T
}
❓ 为什么用它?
  • 在泛型结构体中,如果你没有真正存储 T,Rust 会认为这个结构体和 T 没有关系,可能会在生命周期检查、Drop 顺序上出问题。
  • PhantomData<T> 告诉编译器:“这个结构体跟 T 有关系”,即使我不持有 T 的值。

✅ 例子 3:ZST 特性 - 可重复但无代价

let a = ();
let b = ();
assert_eq!(std::ptr::addr_of!(a), std::ptr::addr_of!(b)); // 地址相同!

7️⃣ _ 占位写法:不关心名字但关心类型

fn consume(_: String) {
    println!("调用了函数,但不需要参数内容");
}
  • _ 表示“我不打算用这个值的名字”,但类型仍然必须匹配。

8️⃣ 底类型 !:不会返回的类型到底有什么用?

❓ 什么是底类型 !

Rust 中的 ! 代表“永不返回”的类型,叫 bottom type。

fn never_return() -> ! {
    panic!("程序终止");
}

✅ 为什么需要 ! 类型?

  • ! 类型可以出现在任何位置,因为它永远不会产生值。
  • 编译器会认为它“能转成任何类型”,就像数学中空集是任何集合的子集。

✅ 典型使用场景

场景示例用途说明
程序崩溃panic!("错误!")程序终止,不再返回
死循环loop {}永远运行,永不返回
编译期保证unreachable!()明确告诉编译器:这里不会执行
match 分支match x { _ => unreachable!() }用于逻辑保证无误的防御性编程

✅ 例子:panic! 与 ! 类型推断

fn get_name(fail: bool) -> String {
    if fail {
        panic!("失败"); // 返回类型是 `!`
    }
    String::from("Tom")
}

虽然两个分支的返回类型不同,但 Rust 会自动推断:! 可以当作任意类型处理,因此允许通过编译。


9️⃣ 总结 + 类型速查表

类型分类示例说明
i32, u8整数let a = 10;默认整数是 i32
f64, f32浮点数let pi = 3.14;默认浮点是 f64
bool布尔let f = true;条件判断
char字符let c = '🚀';Unicode 字符
&str, String字符串"Tom"String::from("Tom")静态与堆上字符串
()ZSTlet x: () = ();单元类型
[T; 0]ZSTlet a: [u8; 0] = [];空数组
struct Marker;ZSTlet m = Marker;类型标记器
PhantomData<T>ZSTPhantomData::<T>类型关联声明
_占位写法fn f(_: T)忽略参数名
!底类型panic!()loop {}不会返回,终结流程分支

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

pumpkin84514

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值