深入理解 Rust 的内存模型:变量、值与指针

文章目录

    • 变量、值与指针
      • [与 C++ 对比](#与 C++ 对比)
    • 高层与低层的变量模型
      • [Rust 高层模型(High-level model)](#Rust 高层模型(High-level model))
      • [Rust 低层模型(Low-level model)](#Rust 低层模型(Low-level model))
      • [与 C++ 对比](#与 C++ 对比)
    • 三大内存区域
      • [1. 栈(Stack)](#1. 栈(Stack))
      • [2. 堆(Heap)](#2. 堆(Heap))
      • [3. 静态内存(Static Memory)](#3. 静态内存(Static Memory))
    • 小结

Rust 以"内存安全"著称,但想真正写出高效、安全的 Rust 代码,就必须理解它背后的内存模型。本篇文章将带你从 变量、值与指针 的概念出发,逐步理解 栈(stack)、堆(heap)和静态内存(static memory) ,以及 Rust 的核心机制------所有权、借用和生命周期 。同时我们还会结合 C++ 的内存模型 做详细对比,方便已经熟悉 C++ 的读者更快地建立对应理解。


变量、值与指针

在 Rust 中:

  • 值(Value) :类型与具体数据的组合。例如,6u8 是一个 u8 类型的值,它在内存中的表示是字节 0x06"Hello world" 是字符串值,它的底层表示是 UTF-8 字节序列。
    • 这里的概念和C++中的字面值是类似的,而 Hello world这种字符串,Rust的类型是 &str,和C++中的 const char* 是类似的
  • 变量(Variable):是一个"命名的位置",用来存储值。变量通常存放在栈上。
  • 指针(Pointer) :保存某个内存地址的值,可以解引用访问其指向的数据。Rust 的引用(&T&mut T)本质上就是指针。
rust 复制代码
let x = 42;
let y = 43;
let var1 = &x;
let mut var2 = &x;
var2 = &y;

这里:

  • 值有四个:4243x 的地址、y 的地址。
  • 变量有四个:x, y, var1, var2

与 C++ 对比

在 C++ 中:

  • :表现形式类似,例如 int x = 42; 中,42 就是值,存放在 x 里。

  • 变量:C++ 的变量和 Rust 类似,通常存储在栈上。但 C++ 不会在编译器层面禁止未初始化使用,例如:

    cpp 复制代码
    int a;  // 未初始化
    std::cout << a; // 未定义行为(UB)

    Rust 则会强制报错,避免 UB。

  • 指针与引用

    • C++ 引用(int&)类似 Rust 的 &T,但 C++ 允许把引用绑定到临时对象上,容易导致悬垂引用;Rust 编译期禁止此类情况。
    • C++ 指针(int*)则与 Rust 的原始指针(*const T, *mut T)接近,需要开发者自己保证安全性。

高层与低层的变量模型

Rust 高层模型(High-level model)

  • 把变量看作值的"名字"。
  • 值的使用抽象为 数据流(flow),一旦值被移动,数据流断开,变量失效。
  • 编译器借用检查器会验证是否存在非法的数据流。

Rust 低层模型(Low-level model)

  • 把变量看作一块内存槽。
  • 赋值覆盖旧数据,引用则是内存的地址。

与 C++ 对比

  • C++ 更接近低层模型:变量就是一块内存,指针/引用直接操作地址。编译器不会阻止危险操作。
  • 在高层抽象上,C++ 缺乏 Rust 那样的"所有权"和"借用检查器"。程序员需要依靠编码规范、智能指针(std::unique_ptr, std::shared_ptr)或工具(如 ASan, Valgrind)来避免内存错误。

示例对比:

cpp 复制代码
int* p = nullptr;
*p = 42; // 未定义行为:空指针解引用

Rust 中:

rust 复制代码
let p: *mut i32 = std::ptr::null_mut();
unsafe {
    *p = 42; // 编译器要求 unsafe 块,显式提示风险
}

Rust 把危险操作显式隔离,C++ 则允许直接执行。


三大内存区域

1. 栈(Stack)

  • Rust:函数调用分配栈帧,局部变量生命周期受作用域限制。

  • C++:相同机制,但 C++ 不会禁止返回局部变量的引用:

    cpp 复制代码
    int& foo() {
        int x = 42;
        return x; // 返回悬垂引用,UB
    }

    Rust:

    rust 复制代码
    fn foo() -> &i32 {
        let x = 42;
        &x // 编译错误:借用不满足生命周期
    }

2. 堆(Heap)

  • Rust:通过 Box<T>Vec<T> 等安全抽象分配,释放由所有权系统自动管理。

  • C++:需要手动 new/delete,或使用智能指针:

    cpp 复制代码
    auto p = std::make_unique<int>(42); // 自动释放

    Rust 的 Box<T> 类似 unique_ptr,但由编译器强制约束,避免误用。

3. 静态内存(Static Memory)

  • Rust:static 变量在程序整个运行期存在,'static 生命周期显式建模。
  • C++:全局变量、静态变量在整个程序运行期间存在,但缺乏生命周期建模,容易导致初始化顺序问题(static initialization order fiasco)。

小结

Rust 的内存安全性来自于编译期的严格规则,而 C++ 则更多依赖程序员经验:

特性 Rust C++
未初始化变量 编译时报错 运行时 UB
指针安全 引用/借用受检查,原始指针需 unsafe 任意指针操作,易出错
所有权 强制存在,编译器跟踪 无,需靠约定或智能指针
生命周期 类型系统显式建模 无,需人工推理
内存回收 RAII + 编译器保证 RAII,但需谨慎设计

可以看到,Rust 在很多地方对 C++ 进行了"强制收紧",牺牲部分灵活性换取编译期的安全性。对于熟悉 C++ 的开发者,可以把 Rust 看作是"有更强类型约束和更严格规则的现代 C++"。

相关推荐
Ray Liang22 分钟前
用六边形架构与整洁架构对比是伪命题?
java·python·c#·架构设计
Java水解38 分钟前
Java 中间件:Dubbo 服务降级(Mock 机制)
java·后端
蚂蚁背大象2 小时前
Rust 所有权系统是为了解决什么问题
后端·rust
布列瑟农的星空2 小时前
前端都能看懂的rust入门教程(五)—— 所有权
rust
SimonKing5 小时前
OpenCode AI辅助编程,不一样的编程思路,不写一行代码
java·后端·程序员
FastBean5 小时前
Jackson View Extension Spring Boot Starter
java·后端
Seven976 小时前
剑指offer-79、最⻓不含重复字符的⼦字符串
java
皮皮林55115 小时前
Java性能调优黑科技!1行代码实现毫秒级耗时追踪,效率飙升300%!
java
冰_河16 小时前
QPS从300到3100:我靠一行代码让接口性能暴涨10倍,系统性能原地起飞!!
java·后端·性能优化