Rust 学习笔记 25:高级特性 (Advanced Features)

“With great power comes great responsibility.” – Uncle Ben (actually unsafe block)

Rust 通常强制执行内存安全规则,但有时我们需要绕过它们(比如操作硬件、与 C 交互)。这时,Unsafe Rust 就派上用场了。 此外,Rust 的 Trait 和类型系统还有很多高级用法,能让你的代码更具表现力。

1. Unsafe Rust

unsafe 关键字给我们开启了 5 种超能力:

  1. 解引用裸指针 (Raw Pointers)。
  2. 调用不安全的函数/方法(包括 FFI)。
  3. 访问或修改可变静态变量 (Mutable Static Variables)。
  4. 实现不安全 Trait (unsafe trait)。
  5. 访问 union 的字段。

裸指针

1let mut num = 5;
2let r1 = &num as *const i32;
3let r2 = &mut num as *mut i32;
4
5unsafe {
6    println!("r1 is: {}", *r1);
7}

编译器不会检查裸指针是否有效、是否为空、是否遵守所有权规则。你自己要负责。

2. 高级 Trait

关联类型 (Associated Types): 在定义 Trait 时指定一个占位符类型,实现时再确定。

1pub trait Iterator {
2    type Item; // 关联类型
3    fn next(&mut self) -> Option<Self::Item>; // 这里的 Item 就是上面的关联类型
4}

它比泛型更适合那种"一个实现只对应一种输出类型"的场景(Point 的加法,结果也只能是 Point,不需要泛型)。

父 Trait (Supertraits): 如果你需要你的 Trait 依赖另一个 Trait(例如实现 OutlinePrint 必须同时实现 Display):

1trait OutlinePrint: fmt::Display { ... }

Newtype 模式: 为了绕过孤儿规则(Orphan Rule:你不能为外部类型实现外部 Trait),我们可以创建一个 Tuple Struct 包装一下:

1struct Wrapper(Vec<String>);
2impl fmt::Display for Wrapper { ... } // 现在可以实现了,因为 Wrapper 是本地类型

3. 高级类型

类型别名 (Type Alias)type Kilometers = i32;,主要用于减少代码重复(如 type Thunk = Box<dyn Fn() + Send + 'static>;)。

Never Type (!): 表示永远不会返回的函数(diverging functions)。例如 fn bar() -> ! { loop {} }

动态大小类型 (DST): 如 str[T]。它们必须通过指针(&str, Box<[T]>)来使用,因为编译器不知道它们在栈上占多大空间。

4. 小结

第25篇笔记。 Unsafe Rust 不是魔鬼,它是构建安全抽象的基石(标准库里到处都是 unsafe,但对外暴露安全的接口)。 高级 Trait 和类型系统则是 Rust “零成本抽象” 的利器。

下一篇,我们将学习 Rust 中最强大也最复杂的特性之一:宏 (Macros)。从简单的 println! 到能生成代码的 derive 宏,宏让 Rust 拥有了元编程的能力。


练习题

  1. 尝试使用 unsafe 修改一个不可变字符串切片的内容(如果发生 Segfault,恭喜你体验了 C/C++ 开发者的日常)。
  2. 实现一个 Add<Meters> for Millimeters,体验带有泛型参数的运算符重载。

思考题

为什么 Rust 的 Iterator trait 使用关联类型 (type Item) 而不是泛型 (Iterator<T>)?这两种设计有什么本质区别?(提示:一个类型可以为多种泛型参数实现同一个 Trait,但只能指定一次关联类型)。


本文代码示例

关注公众号:极客老墨

更多 AI 应用开发、工程实践和效率工具分享,欢迎扫码关注。

极客老墨微信公众号二维码

相关阅读