847 字
4 分钟
所有权

核心定义#

所有权是 Rust 的核心内存管理机制,基于三条规则:

  1. 每个值有唯一所有者(变量)
  2. 值离开作用域时自动释放
  3. 所有权可通过移动(move)转移(如赋值/传参),或通过借用(borrow)临时共享 此机制在编译期消除数据竞争和内存错误(空指针/内存泄漏),无需垃圾回收。

工作原理#

编译器跟踪每个值的生命周期:

  1. 移动语义:当值赋给新变量或传入函数,所有权转移(原变量失效)
  2. 借用检查:通过引用(&T/&mut T)临时访问值,强制执行读写锁规则(N写 or 1读)
  3. 作用域结束:所有者离开作用域时,自动调用 drop 释放内存
flowchart TD 
	A[创建值 owner = String::new] --> B{操作类型} 
	B -->|移动| C[新所有者 new_owner = owner] 
	B -->|借用| D[创建引用 ref = &owner] 
	C & D --> E[离开作用域] 
	E -->|移动后| F[原owner无效]
	E -->|借用的值| G[值被释放]

关键点#

  1. 移动而非复制:未实现 Copy 的类型(如 String)赋值时转移所有权
  2. 借用规则
    • 任意数量不可变引用(&T
    • 唯一可变引用(&mut T
  3. 函数交互:传参转移所有权,返回值可返回所有权
  4. 克隆显式复制clone() 深拷贝数据
  5. 解构移动:模式匹配(match)可能转移字段所有权

常见误区#

  1. 意外移动:循环中使用集合迭代器(for x in vec 转移所有权)
  2. 悬垂引用:返回局部变量引用(fn f() -> &str { &String::new() }
  3. 误用克隆:过度使用 clone() 导致性能下降
  4. 部分移动:解构未实现 Copy 的结构体(如 let p = Point { x: String::new(), y: 1 }; let x = p.x; 后 p.y 仍可用但 p 部分失效)
  5. 借用冲突:同时创建可变和不可变引用(let r1 = &s; let r2 = &mut s;

应用场景#

场景示例所有权作用
避免数据竞争let mut s = String::new(); let r1 = &s; let r2 = &s;允许多读
安全资源管理File::open("a.txt") → 离开作用域自动关闭文件替换 try-finally 块
高效内存传递fn take(s: String) { ... } take(my_string)移动而非深拷贝
智能指针实现Box::new() / Rc::new()明确堆内存所有权
零成本抽象自定义类型实现 Drop trait释放时执行自定义逻辑(如网络连接)

关联知识#

  1. 生命周期(Lifetimes):编译器验证引用有效性的辅助标记
  2. 借用检查器(Borrow Checker):在编译期强制执行所有权规则
  3. 智能指针
    • Box<T>:独占堆内存所有权
    • Rc<T>/Arc<T>:共享所有权(引用计数)
    • RefCell<T>:运行时借用检查
  4. Copy 与 Clone
    • Copy:位复制(编译器自动处理,如 i32
    • Clone:显式深拷贝(需调用 .clone()
  5. 模式匹配:解构时可能转移所有权(尤其未实现 Copy 的类型)
  6. 并发安全:所有权系统是实现 Send/Sync 的基础
  7. 错误处理:所有权转移与 ? 运算符交互(如 File::open?

💡 黄金法则

移动后失效:值被移动后原始绑定立即失效 引用不拥有:借用(引用)不获取所有权,仅临时访问 作用域即生命周期:变量离开作用域时值被释放 优先让编译器报错指导修复,而非强行 clone()

所有权
https://website-truelovings-projects.vercel.app/posts/rust/所有权/
作者
欢迎来到StarSky的网站!
发布于
2025-08-17
许可协议
CC BY-NC-SA 4.0