Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

关于 Rust 的一些思考

1. Rust 最大的四个优势

  1. Cargo如果你让一个 C++ 程序员第一次接触 Cargo,他一定会爱上它。这种开箱即用的包管理和构建工具,在 C++ 生态中完全找不到。
  2. 友好的错误提示Rust 的编译器错误信息非常清晰、实用,比起 C++ 那堆抽象的模板报错好上太多。
  3. 函数是第一公民Rust 中函数可以作为参数、返回值,支持闭包,函数式编程体验流畅。
  4. 轻量级 OOP Rust 保留了面向对象的一些影子,但做了很好的解耦。
    • 封装 : struct依旧保持了抽象的能力,聚焦于数据结构的抽象。同时mod依旧有访问控制
    • 多态 : 基于trait对象也能实现动态多态。
    • 继承 : 砍掉继承,解耦实体之间的关系,组合替代继承,强调组合优于继承。
  5. 所有权机制 这个是把双刃剑
    • 优势:
      • 把C++的核心内存管理思想和遇到的内存问题内化成语法规则,最大程度在编译阶段解决内存问题
      • 显示生命周期标注,解决了 C++ 中的悬空引用问题,并且把生命周期分析显式标注,更能直观反应出对象的生命周期
    • 劣势: 过于严格的检查,导致代码灵活性下降;并且面向编译器编程

2. Rust 目前最大的问题

代码的灵活性与安全性难以兼得 C++ 很容易写出编译正确但实际运行错误的代码;而 Rust 则很容易写出实际逻辑正确但编译不通过的代码。 借用检查器仍然需要继续迭代和优化。

3. Rust 的三大难点

3.1 内存管理(所有权机制)

很多人觉得所有权机制本身难理解,但我不这么认为。所有权机制的本质,其实是对 C++ 内存管理思想的内化(RAII、手动内存释放等)。 那为什么很多人觉得难? 因为 Rust 在用户层面隐藏了手动内存分配和 RAII 的具体实现细节。初学者无法像在 C++ 中那样,直观地通过代码感受 RAII 的魅力——你可以亲手写一个类的构造/析构函数,看到内存何时申请、何时释放。 Rust 做不到这一点,它把底层思想“藏”了起来,这才导致了所有权机制的理解门槛。

3.2 宏(Macro)

Rust 的宏和 C 的宏完全是两个东西。

  • 初学 Rust 泛型时,你会觉得它比 C++ 的泛型少了某些能力。
  • 后来才发现,Rust 把很多元编程能力从泛型“移”到了宏,尤其是声明宏
  • 而最难理解的无疑是过程宏。它直接介入编译过程,你需要了解编译原理中的 tokenCSTAST 等概念,才能写出正确的过程宏。

3.3 Async(异步)

我认为 Rust 最大的失败之一,就是把这套机制叫做“异步编程”。它其实不应该叫这个名字,更应该叫 async 状态机

  • 它本身不具备异步能力,你无法仅依靠标准库轻松写出一个异步程序。它只是可以用来实现异步的底层机制。
  • Rust 的 async 和 C++ 的协程在设计上是趋同的,但又有很大不同:
    • 两者本质都是无栈协程,由编译器转换为状态机,都只定义了接口和语义,没有具体的调度实现。
    • 但 C++ 的设计语义非常一致,都是围绕协程本身的“挂起 / 恢复”这一语义。
    • Rust 的视角则比较刁钻:虽然用了 async/await 关键字,但其中的 FutureContextWaker 其实是纯粹的 task-runtime 语义。这就导致你要理解 async,就完全无法脱离 runtime。而对于初学者来说,自己去实现一个 runtime 是非常困难的。

4. 学习 Rust 需要转变的两个思维

4.1 关注每一个对象的生命周期

你需要学会从对象生命周期的角度去设计程序。 C 和 C++ 程序员已经比较习惯这种思维模式,但和其他语言的开发者交流时,会发现他们往往没有这个习惯。 另外,目前 AI 在复杂项目中,对众多对象的生命周期管理和分析能力仍然欠佳。

4.2 默认移动而非拷贝(针对 C++ 程序员)

C++ 中普通值的默认语义更偏向拷贝;当你想表达资源转移时,通常需要显式调用 std::move。 而 Rust 对非 Copy 类型的默认语义是移动,这一点在思维上需要主动转变。