Rust基础-part5-引用
Rust基础[part5]_引用
- 不可变引用:通过不可变引用,可以读取变量,但是不能够修改数据。一个变量可以有多个不可变引用,但不能与可变引用共存。
- 可变引用:通过可变引用,可以读取和修改数据。一个变量在某一时刻只能有一个可变引用,且不能与不可变引用共存。
引用规则
- 同一时间(生命周期)内,一个变量只能有一个可变引用或多个不可变引用
- 多个不可变引用可以共存
- 可变引用必须是独占的(不能与其他引用共存)
- 引用必须总是有效(Rust保证引用永远不会指向无效内存)
示例1:错误示范
pub fn reference_example() {let mut s: String = String::from("Hello");// 创建不可变引用let s1: &String = &s;// 创建可变引用(错误:此时s已有不可变引用)let s2: &mut String = &mut s;// 错误:不能创建多个可变引用let s3: &mut String = &mut s;// 错误:同一生命周期内同时使用不可变和可变引用println!("s1: {}, s2: {}", s1, s2);
}
示例 2:正确示范
pub fn reference_example() {let mut s: String = String::from("Hello");// 第一阶段:仅使用不可变引用let s1: &String = &s;println!("s1: {}", s1); // s1在此处不再使用// 第二阶段:创建可变引用(s1已不再活跃)let s2: &mut String = &mut s;println!("s2: {}", s2);
}
切片(Slices)
数组切片
let a = [1, 2, 3];let b = & a[0..1];let c = & a[0..=1];
字符串切片
是对字符串部分内容的引用
// 字符串引用let s = String::from("Hello, Rust!");let slice1: &str = &s[0..5]; // "Hello"let slice2: &str = &s[7..]; // "Rust!"let slice3: &str = &s[..]; // "Hello, Rust!"
悬垂引用(Dangling Reference)
生命周期核心规则:引用的生命周期必须 ≤ 被引用对象的生命周期
错误示例1:
pub fn dangling_pointer_example() {let r: &String;{let s = String::from("Hello"); // s的生命周期仅在{}内r = &s; // r引用s,但s即将被销毁} // s在此处被释放println!("r: {}", r); // 错误:r引用的s已不存在(悬垂引用)
}
关键点:
- s的生命周期:从创建到
}
结束。 - r的生命周期:从创建到函数结束(覆盖
s
的生命周期)。 - 错误原因:
r
存活时间超过s
,导致引用无效。
错误示例2:
fn get_a() -> &String { // 错误:返回局部变量的引用let s = String::from("a");&s // 函数结束后s被销毁,引用悬空
}
关键点:
- 返回引用的合法性:只能返回参数或全局变量的引用,不能返回局部变量的引用。
正确示例:
生命周期注解(Lifetime Annotation)
pub fn lifetime_example() {let large = longest("a", "ab");println!("The longest string is: {}", large);// 生命周期注解:确保返回的引用与参数生命周期一致fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {if x.len() > y.len() { x } else { y }}
}
关键点:
'a
的含义:参数x
和y
以及返回值的引用必须至少存活到'a
结束。- 编译器检查:
- 验证
x
和y
的实际生命周期是否满足'a
。 - 确保返回值的生命周期不超过
'a
。
- 验证
- 实际效果:返回的引用在调用者的作用域内有效(如
large
的生命周期覆盖longest
的调用)。
总结:避免悬垂引用的3种方式
- 返回所有权(如
fn get_a() -> String
):转移值的控制权,无需引用。 - 引用外部变量(如
fn get_a(s: &String) -> &String
):确保被引用对象生命周期足够长。 - 生命周期注解(如
fn longest<'a>(x: &'a str) -> &'a str
):明确引用的合法存活范围。