Rust 最具特色的就是它的 所有权机制(Ownership)智能指针(Smart Pointer),这也是它实现 无垃圾回收(GC)却仍然内存安全 的核心设计。本篇文章将带你深入理解这两个关键概念。


一、所有权机制(Ownership)

Rust 的内存管理不依赖垃圾回收器,而是依赖于所有权规则

所有权三原则:

  1. 每个值都有一个所有者(owner)

  2. 同一时间只能有一个所有者

  3. 当所有者离开作用域,值被释放(drop)

示例 1:移动(move)

fn main() {
    let s1 = String::from("hello");
    let s2 = s1; // s1 的所有权移动给 s2

    // println!("{}", s1); // ❌ 报错:s1 已无效
    println!("{}", s2); // ✅ 正常
}

示例 2:克隆(clone)

fn main() {
    let s1 = String::from("hello");
    let s2 = s1.clone(); // 深拷贝,s1 仍然有效

    println!("{}, {}", s1, s2); // ✅ 正常
}

示例 3:借用(borrow)

fn main() {
    let s1 = String::from("hello");

    // 不可变借用
    print_str(&s1);
    println!("{}", s1); // ✅ s1 仍可用
}

fn print_str(s: &String) {
    println!("打印字符串:{}", s);
}

示例 4:可变借用

fn main() {
    let mut s = String::from("hello");

    change(&mut s);
    println!("{}", s); // 输出:hello world
}

fn change(s: &mut String) {
    s.push_str(" world");
}

二、智能指针(Smart Pointer)

智能指针是实现复杂所有权语义的结构,提供堆内存管理、共享引用、内部可变性等功能。

类型

功能说明

线程安全

适用场景

Box<T>

堆分配、值唯一所有权

大对象或递归结构,如链表、树等

Rc<T>

引用计数,允许多个所有者

多个只读所有者(单线程)

Arc<T>

原子引用计数,多线程共享

多线程共享数据,线程安全

RefCell<T>

运行时内部可变性(单线程)

需要在不可变引用中进行可变操作

Cell<T>

拷贝类型的内部可变性

简单值如整数的内部变更

示例 1:Box<T> —— 堆上分配

fn main() {
    let b = Box::new(10); // 10 存储在堆上
    println!("Box 值: {}", b);
}

示例 2:Rc<T> —— 多个所有者(单线程)

use std::rc::Rc;

fn main() {
    let a = Rc::new(String::from("hello"));
    let b = Rc::clone(&a);
    let c = Rc::clone(&a);

    println!("引用计数: {}", Rc::strong_count(&a)); // 3
    println!("内容: {}", b);
}

示例 3:Arc<T> —— 多线程共享

use std::sync::Arc;
use std::thread;

fn main() {
    let data = Arc::new(vec![1, 2, 3]);

    for _ in 0..3 {
        let data_cloned = Arc::clone(&data);
        thread::spawn(move || {
            println!("{:?}", data_cloned);
        });
    }
}

示例 4:RefCell<T> —— 内部可变性(单线程)

use std::cell::RefCell;

fn main() {
    let data = RefCell::new(String::from("hello"));
    data.borrow_mut().push_str(" world");

    println!("{}", data.borrow());
}

示例 5:Cell<T> —— 拷贝类型的可变性

use std::cell::Cell;

fn main() {
    let cell = Cell::new(5);
    cell.set(10);
    println!("Cell 中的值: {}", cell.get());
}

三、小结

Rust 中的所有权和智能指针共同实现了 零成本抽象(zero-cost abstraction),即在没有运行时开销的前提下,提供强大的内存管理能力。

特性

是否编译期检查

是否线程安全

是否可变借用

使用场景

所有权

❌(默认不可)

默认内存模型

Box<T>

大对象堆分配

Rc<T>

❌(运行时)

多个只读引用(UI 树、配置等)

Arc<T>

❌(运行时)

多线程读共享

RefCell<T>

❌(运行时)

单线程下的内部可变

Cell<T>

❌(运行时)

✅(拷贝类型)

小型数据内部可变


本站由 困困鱼 使用 Stellar 创建。