
本章系统讲解 Rust 的所有权(Ownership)模型,它是 Rust 在无 GC 的前提下实现内存安全与高性能的关键机制。你将理解“值的唯一所有者”、移动(move)、复制(copy)、释放(drop),以及与之相关的借用(borrow)与切片(slice)等基础概念,并能看懂和修复典型报错。
fn main() {
let s = String::from("hello"); // s 拥有 String 的所有权
takes_ownership(s); // 所有权移动到函数参数
// println!("{}", s); // E0382: s 已被移动,不能再使用
let x = 42;
makes_copy(x); // i32 实现 Copy,不发生 move
println!("x 仍然可用: {}", x); // OK
}
fn takes_ownership(s: String) {
println!("got {}", s);
} // s 离开作用域,自动 drop
fn makes_copy(n: i32) {
println!("n = {}", n);
} // n 离开作用域,但为栈上 Copy 类型,无需 drop
String, Vec<T>, 自定义类型等)。bool, char,以及仅由 Copy 成员组成的 #[derive(Copy, Clone)] 结构体)。#[derive(Copy, Clone)]
struct Point { x: i32, y: i32 }
fn main() {
let a = Point { x: 1, y: 2 }; // Copy
let b = a; // 复制,不是 move
println!("a=({}, {}), b=({}, {})", a.x, a.y, b.x, b.y);
let s1 = String::from("hi");
let s2 = s1; // move
// println!("{}", s1); // E0382: moved
println!("{}", s2);
}
判断是否 Copy 的经验法:若类型需要自定义释放逻辑或拥有堆资源,通常不是 Copy。
如需保留原变量且获得一份独立数据,使用 clone():
fn main() {
let s1 = String::from("hello");
let s2 = s1.clone(); // 深拷贝
println!("s1={}, s2={}", s1, s2);
}clone 可能有性能开销,按需使用。

&T,可读不可写,可同时存在多个。&mut T,可写,但同一作用域内同一数据“至多一个可变借用”且不可与任意共享借用并存。fn main() {
let mut s = String::from("abc");
let r1 = &s; // 共享借用
let r2 = &s; // 共享借用可以多个
println!("{}, {}", r1, r2);
// let r3 = &mut s; // E0502: 不能在有共享借用的同时创建可变借用
let r3 = &mut s; // 当前作用域内没有活动的共享借用,OK
r3.push_str("def");
println!("{}", r3);
}
常见错误:
Rust 禁止产生悬垂引用:
fn dangle() -> &String { // 编译错误:返回引用但被引用的值将被释放
let s = String::from("hi"); // s 在函数结束时被 drop
&s // 返回悬垂引用 -> 被拒绝
}生命周期(lifetime)用于在编译期证明引用始终有效。详细内容见 5.3。
函数返回值会将所有权转移给调用者:
fn main() {
let s = give_ownership(); // 所有权从函数返回给 s
let t = take_and_return(s); // s 移动到函数,再由返回值给 t
println!("{}", t);
}
fn give_ownership() -> String {
String::from("data")
}
fn take_and_return(x: String) -> String {
println!("got {}", x);
x
}切片是对集合中一段连续元素的“只读借用”,本身不拥有数据:
fn first_word(s: &str) -> &str { // 接受 &str(字符串切片)
let bytes = s.as_bytes();
for (i, &b) in bytes.iter().enumerate() {
if b == b' ' { return &s[..i]; }
}
&s[..]
}
fn main() {
let s = String::from("hello world");
let w = first_word(&s); // 将 String 借为 &str
println!("{}", w);
}切片常见于:&str, &[T], &mut [T]。
clone() 或重新获取所有权(函数返回)。let mut s = String::from("hi");
let a = &s;
let b = &mut s; // 错误:共享与可变借用冲突
println!("{}", a);keep_longer<'a>(a: &'a str, b: &'a str) -> &'a str,返回更长的切片。到这里你已掌握所有权的核心逻辑。下一节我们将系统学习“借用与引用”的规则与实战技巧,再下一节深入生命周期。