一、所有权三大规则(必背)
- 每个值都有唯一所有者。
- 同一时间只能有一个所有者。
- 所有者离开作用域,值自动销毁(drop)。
二、赋值行为:Copy / Move
1. Copy 类型(栈数据)
-
赋值 / 传参:位拷贝,复制值
-
原变量保留有效
-
类型:
i32/u8/f64/bool/char/&T/&str/全Copy元组数组let a = 10;
let b = a; // Copy
println!("{} {}", a, b); // 正常
2. 非 Copy 类型(堆数据)
-
赋值 / 传参:所有权移动 Move
-
原变量失效
-
类型:
String/Vec/Box/自定义结构体等let s1 = String::from("hello");
let s2 = s1; // Move
// println!("{}", s1); // 报错:borrow of moved value
三、引用与借用(Borrowing)
借用 = 获取引用,不转移所有权
1. 不可变引用 &T(共享引用)
-
可同时存在多个
-
只读,不可修改
-
语法:
&变量let s = String::from("hi");
let r1 = &s;
let r2 = &s;
println!("{} {}", r1, r2); // 合法
2. 可变引用 &mut T(独占引用)
-
同一时间只能有一个
-
可读、可修改
-
原变量必须是
mut -
不可与不可变引用同时存在
let mut s = String::from("hi");
let r = &mut s;
r.push_str(" rust"); // 可修改
四、解引用 * 与自动解引用(.)
1. 手动解引用 *
-
&T是引用,*引用拿到原始值let x = 10;
let p = &x;
assert_eq!(*p, 10); // *p 解引用let mut x = 10;
let p = &mut x;
*p = 20; // 通过可变引用修改原值
2. 自动解引用(. 运算符)
-
Rust 对
.会自动解引用 ,无需手动写* -
s.len()等价于(*s).len()let s = &String::from("hello");
s.len(); // 自动解引用 &String → String
规则:
变量.方法→ Rust 自动套用&/*/&mut匹配类型
五、引用 / 解引用 与 Copy 的关系
-
&T本身是 Copy 类型引用赋值是拷贝引用,不是移动。
let a = 10;
let r1 = &a;
let r2 = r1; // Copy,r1、r2都有效 -
对非 Copy 类型的引用:
引用本身可 Copy,但底层数据不可 Copy
let s = String::from("abc");
let r1 = &s;
let r2 = r1; // 拷贝引用,没问题
// let s2 = s; 才是 Move
六、借用三大黄金规则
- 要么 多个不可变引用 &T ,要么 一个可变引用 &mut T,不可共存。
- 引用不能悬垂(dangling),不能指向已销毁的值。
- 可变引用独占、排他,保证线程安全与无数据竞争。
七、Copy 与借用的选择
-
Copy 类型:直接传值,简单高效。
-
非 Copy 类型 :必须用 &T / &mut T 借用,避免所有权转移。
// Copy:传值
fn add(a: i32, b: i32) -> i32 { a + b }// 非Copy:传引用
fn len(s: &String) -> usize { s.len() }
极简一句话
- 所有权:值有主人,离开作用域销毁。
- Copy:栈类型,赋值拷贝,原值保留。
- Move:堆类型,赋值移走所有权,原值失效。
- &T:共享只读引用,可多份,Copy。
- &mut T:独占可变引用,仅一份,可修改。
\*:手动解引用;.:自动解引用。- 借用规则:不可变共享、可变独占,不同时存在,无悬垂引用。