目录

第5章:所有权系统

什么是所有权?

所有权(Ownership)是 Rust 最独特的特性,它让 Rust 无需垃圾回收器即可保证内存安全。所有权的三条规则:

1. Rust 中的每个值都有一个**所有者**变量
2. 同一时间只能有一个所有者
3. 当所有者离开作用域,值被自动释放

所有权规则一:每个值只有一个所有者

fn main() {
    let s1 = String::from("hello");
    let s2 = s1; // s1 的所有权转移给 s2
 
    // println!("{}", s1); // 编译错误:s1 已被移动(moved)
    println!("{}", s2);    // 正常:s2 是所有者
}

这称为移动(Move)。移动后原变量失效,避免了双重释放。

Copy 类型

标量类型实现了 Copy trait,赋值时是拷贝而非移动:

fn main() {
    let x = 5;
    let y = x; // x 仍然是有效的拷贝
    println!("x={}, y={}", x, y); // 都能访问
 
    // 实现 Copy 的类型:
    // - 所有整数类型
    // - 浮点类型
    // - 布尔类型
    // - 字符类型
    // - 元组(仅包含 Copy 类型时)
}

函数参数的所有权

传递变量给函数也会转移所有权:

fn take_ownership(s: String) {
    println!("我拥有了: {}", s);
} // s 在此释放
 
fn main() {
    let s = String::from("hello");
    take_ownership(s);
    // println!("{}", s); // 编译错误:所有权已转移
}

返回值转移所有权

fn give_ownership() -> String {
    let s = String::from("world");
    s // 返回所有权给调用者
}
 
fn main() {
    let s = give_ownership();
    println!("{}", s); // 正常:s 现在拥有所有权
}

Clone:显式深拷贝

如果确实需要复制堆上的数据,用 clone()

fn main() {
    let s1 = String::from("hello");
    let s2 = s1.clone(); // 深拷贝堆数据
 
    println!("s1 = {}, s2 = {}", s1, s2); // 都能访问
}

注意:clone() 是显式的,意味着开发者意识到这是昂贵的操作。

栈与堆

栈(Stack):后进先出,快速。存储大小固定的数据。

堆(Heap):慢速,大小未知或动态变化的数据。分配时返回指针。

fn main() {
    // i32 大小固定(4字节),在栈上
    let x: i32 = 42;
 
    // String 大小可变,数据在堆上,指针在栈上
    let s: String = String::from("hello");
    // s 本身在栈上(指针+长度+容量)
    // "hello" 数据在堆上
}

本章小结