3.1 所有权规则与栈/堆内存模型
听
Rust 的所有权系统是一套在编译期强制执行的规则,用于管理程序如何使用内存。它不需要垃圾回收器,也不依赖程序员手动调用 free,而是通过静态分析确保内存安全。要理解所有权,首先需要了解 Rust 如何在内存中存储数据,尤其是栈(stack)和堆(heap)的区别。
栈与堆
栈是一种后进先出(LIFO)的数据结构,存取速度快,但大小在编译时必须已知且固定。所有基本类型(如整数、布尔值、字符等)都存储在栈上。
堆则用于存储在运行时才能确定大小或生命周期不确定的数据。访问堆上的数据比栈慢,因为需要通过指针间接访问,并涉及内存分配和释放操作。
例如,String 类型在栈上保存指向堆中实际字符串内容的指针、长度和容量信息,而真正的文本数据则存放在堆上。
所有权的基本规则
Rust 的所有权系统基于以下三条核心规则:
- Rust 中的每个值都有一个被称为其所有者(owner)的变量。
- 值在任意时刻只能有一个所有者。
- 当所有者离开作用域时,该值将被自动丢弃(调用
drop函数),释放其占用的资源。
这些规则共同保证了内存不会被重复释放,也不会发生泄漏。
作用域与资源释放
变量的作用域从其声明处开始,到当前代码块结束为止。当变量离开作用域时,Rust 会自动调用 drop 清理资源。
{
let s = String::from("hello"); // s 进入作用域
// 使用 s
} // s 离开作用域,drop 被调用,堆内存被释放
这种“资源获取即初始化”(RAII)模式是系统编程中管理资源的经典方法,Rust 将其作为语言核心机制。
示例:所有权转移
考虑以下代码:
let s1 = String::from("hello");
let s2 = s1;
// println!("{}", s1); // 错误:s1 不再有效
当 s1 被赋值给 s2 时,所有权从 s1 转移到 s2,s1 不再可用。这是为了防止两个变量同时拥有同一堆内存的所有权,从而避免双重释放(double free)错误。
这种行为与栈上数据(如整数)不同,后者默认会被复制而非移动。我们将在下一节详细讨论移动与复制的区别。
小结
所有权规则结合栈/堆内存模型,构成了 Rust 内存安全的基础。通过在编译期追踪每个值的所有者及其生命周期,Rust 能够在不牺牲性能的前提下,消除大量常见的内存错误。理解这些基本概念,是掌握后续借用、引用和生命周期机制的前提。
#Rust 入门教程
分享于 1 周前
上一篇:第三章:所有权系统详解
下一篇:3.2 移动语义与复制语义