Rust入门系列第五篇。所有权是 Rust 最具特色的理念,也是它在没有垃圾回收器的情况下依然内存安全的原因。
三条规则#
- Rust 中每个值都有一个所有者。
- 同一时间只能有一个所有者。
- 当所有者离开作用域,值即被释放。
fn main() {
let s = String::from("hello");
println!("{s}");
} // s 离开作用域;内存被释放rustMove 语义#
把值赋给另一个变量会移动所有权——旧的绑定不能再使用:
let s1 = String::from("hello");
let s2 = s1;
// println!("{s1}"); // 错误:值已被移动
println!("{s2}"); // 可以rust字符串没有被复制;它的数据和所有权都移给了 s2。这正是 Rust 没有 use-after-free 漏洞的原因。
Copy 类型#
复制成本低的小类型会被复制而非移动。它们实现了 Copy trait:
let a = 5;
let b = a; // a 仍可使用rust整数、浮点数、布尔和 char 都是 Copy。String 和 Vec 不是。
Clone#
要复制堆上分配的值,需要显式调用 .clone():
let s1 = String::from("hello");
let s2 = s1.clone();
println!("{s1} {s2}"); // 两者都有效rustclone 做深拷贝。显式调用让成本一目了然。
所有权与函数#
把值传给函数会移动它;返回它又会移回来:
fn take_and_return(s: String) -> String {
s
}
fn main() {
let s = String::from("hi");
let s = take_and_return(s); // 移入,再移出
}rust所有权与作用域#
当所有者的作用域结束时,值即被释放。基于作用域的清理意味着资源——不只是内存——都会被自动释放。
为什么重要#
所有权让编译器能够证明不存在 use-after-free、double-free 和悬垂指针——这些正是困扰 C 和 C++ 的 bug。你写普通代码,编译器强制执行安全。
结论#
所有权:每个值一个所有者,默认 move,Copy 类型复制,深拷贝用显式 clone。本系列下一篇:引用与切片。