Borring && Borrow Checker && Lifetime
Borrowing(引用的函数式声明)
一个玩意的两种描述
引用(reference):
-
引用是一种变量的别名,通过 & 符号来创建(非所有权)
-
引用可以是不可变的(&T)或可变的(&mut T)
-
引用允许在不传递所有权的情况下访问数据,他们是安全且低开销的
借用(Borrowing):
-
借用是通过引用(Reference)来借用(Borrow)数据,从而在一段时间内访问数据而不借用它
-
借用氛围可变借用和不可变借用。可变借用(&mut)允许修改数据,但在生命周期内只能有一个可变借用。不可变借用(&)允许多个同时存在,但不允许修改数据
Borrow Checker
-
不可变引用规则:
在任何给定的时间,要么有一个可变引用,要么有多个不可变引用,但不能同时存在可变引用与不可变引用。这确保了在同一时间内只有一个地方对数据进行修改,或者有多个地方同时读取数据 -
可变引用规则
在任何给定的时间,只能有一个可变引用来访问数据。这防止了并发修改相同数据的问题,从而防止数据竞争 -
引用的生命周期必须在被引用的数据有效时间范围内。这防止了悬垂引用,即引用的数据已经被销毁,但引用仍然存在
-
可变引用与不可变引用不互斥
可以同时存在多个不可变引用,因为不可变引用不会修改数据,不会影响到其他引用。但不可变引用与可变引用之间是互斥的。
fn main(){
let mut s = String::from("Hello");
let r1 = &s;
let r2 = &s;
println!("{} {}", r1, r2);
let r3 = &mut s;
println!("{}", r3);
let result: &str;
{
// result = "hello"; // 初始化不影响生命周期
let r4 = &s;
result = ff(r4);
}
println!("{}", result);
}
fn ff<'a>(s: &'a str) -> &'a str {
s
}
Lifetime 与 函数
大多数情况下,生命周期是隐式且被推断的
生命周期的主要目的是防止悬垂引用
关于"悬垂引用”的概念是指,引用指向的数据在代码结束后被释放,但引用仍然存在。生命周期的引入有助于确保引用的有效性,防止程序在运行时出现悬垂引用的情况。通过生命周期的推断,Rust能够在编译时检查代码,确保引用的有效性而不是在运行时出现悬垂引用的错误。
编译器在没有显式注解的情况下,使用三个规则来推断这些生命周期:
-
第一个规则是每个作为引用的参数都会得到它自己的生命周期参数。
-
第二个规则是,如果只有一个输入生命周期参数,那么该生命周期将被分配给所有输出生命周期参数(该生命周期将分配给返回值)。
-
第三个规则是,如果有多个输入生命周期参数,但其中一个是对self或不可变se|f的引用时。因为在这种情况下它是一个方法,所以se|f的生命周期被分配给所有输出生命周期 参数
fn longest<'a>(s1: &'a str, s2: &'a str) -> &'a str {
if s1.len() > s2.len() {
s1
} else {
s2
}
}
fn longest_str<'a, 'b, 'out>(s1: &'a str, s2: &'b str) -> &'out str
where
'a : 'out,
'b : 'out,
{
if s1.len() > s2.len() {
s1
} else {
s2
}
}
fn no_need(s: &'static str, s1: &str) -> &'static str{
s
}
fn main(){
println!("no need {}", no_need("hh", "nn"));
let s1 = "hello world";
let s2 = "hello";
println!("longest {}", longest(s1, s2));
}
Lifetime 与 Struct
结构体的引用
-
在结构体中的引用需要标注生命周期
-
结构体的方法(&self等)不需要标注生命周期
struct MyStruct<'a>{
text: &'a str,
}
impl<'a> MyStruct<'a>{
fn get_length(&self) -> usize{
self.text.len()
}
fn modify_data(&mut self) {
self.text = "world2";
}
}
struct StringHolder{
data: String,
}
impl StringHolder{
fn get_length(&self) -> usize{
self.data.len()
}
fn get_reference<'a>(&'a self) -> &'a String{
&self.data
}
fn get_ref(&self) -> &String{
&self.data
}
}
fn main(){
let str1 = String::from("hello");
let mut x = MyStruct{
text: str1.as_str(),
};
x.modify_data();
println!("{}", x.get_length());
let y = StringHolder{
data: "hello".to_owned(),
};
println!("{}",y.get_reference());
println!("{}",y.get_ref());
}
标签:生命周期,入门,self,简易,let,引用,str,fn,Rust
From: https://www.cnblogs.com/moguw/p/18105924/rust-base-5