主题
所有权
每个值有且只有一个 owner。owner 离开作用域时值被释放。赋值和传参默认 move:原绑定失效。这是内存安全的来源,不是可选风格。
rust
let a = String::from("demo");
let b = a; // a 已 move,不能再使用实现 Copy 的类型(整数、布尔、共享引用等)赋值时复制位模式,原绑定仍可用。String、Vec、拥有堆数据的类型不实现 Copy。
需要两份独立数据时用 clone()。它按值深拷语义复制,有分配成本,不应当作绕过借用检查的默认手段。
借用
&T 共享借用,可同时存在多份,不能通过它修改。&mut T 独占借用,同一时刻只能有一份,允许修改。
rust
fn len(s: &str) -> usize {
s.len()
}
fn push_bang(s: &mut String) {
s.push('!');
}同一作用域内:多个 &T,或一个 &mut T,二者不能并存。借用必须短于 owner 的生命周期。
API 边界
| 需求 | 参数 | 返回 |
|---|---|---|
| 只读查看 | &T / &str | &T(仍由调用方持有) |
| 需要修改 | &mut T | 通常不返回内部引用 |
| 需要所有权 | T | T |
接收文本优先 &str,存储文本用 String。调用方有 String 时会自动解引用成 &str。
函数返回内部引用时,生命周期必须出现在签名上,告诉编译器引用从哪份输入借出:
rust
fn first<'a>(items: &'a [String]) -> Option<&'a str> {
items.first().map(String::as_str)
}结构体持有引用时同样要标生命周期。能改成持有 String / Vec 就不必把生命周期传遍调用链。
内部可变性
&T 不能改内部字段。需要在共享引用下修改时用 Cell、RefCell(单线程)或 Mutex、RwLock(跨线程)。它们把借用检查推迟到运行时或锁协议,不是所有权规则的例外。
