Rust的引用与借用

我爱海鲸 2024-01-26 17:29:18 rust学习

简介reference、borrow

1、引用(reference)

fn main() {
    let _s1 = String::from("我爱海鲸");

    let s = calculate_length(&_s1);

    println!("{}",s)

}

fn calculate_length(s:&String) ->usize{
    let len = s.len();
    len
}

“&”表示取变量的地址,也就是引用的意思,上面的代码中也就是我们没有把变量的所有权传递过去,而是传递了变量的引用,所有权还是保留在main函数中。

参数的类型是&String 而不是String

&符号就表示引用:允许你引用某些值而不取得其所有权

2、借用

我们把引用作为函数参数这个行为叫做借用

那我们怎么通过引用来修改变量的值呢?上代码

fn main() {
    let mut _s1 = String::from("我爱海鲸");

    let s = calculate_length(&mut _s1);

    println!("{}",s)

}

fn calculate_length(s: &mut String) ->usize{
    s.push_str(",ok");
    let len = s.len();
    len
}

可变引用有一个重要的限制:在特定作用域内,对某一块数据,只能有一个可变的引用。

例如:

let mut s:String = String::from("Hello World")

let s1 = &s;

let s2 = &s;

这样就有问题了。

这样做的好处是可在编译时防止数据竞争。

以下三种行为下会发生数据竞争:

一两个或多个指针同时访问同一个数据

至少有一个指针用于写入数据

没有使用任何机制来同步对数据的访问

可以通过创建新的作用域,来允许非同时的创建多个可变引用

fn main() {
    let mut _s = String::from("我爱海鲸");

    {
        let _s1 = &mut_s;
    }
    

    let _s2 = &mut_s;


}

不可以同时拥有一个可变引用和一个不变的引用

多个不变的引用是可以的

fn main() {
    let mut st = String::from("我爱海鲸");

    let r1 = &st;

    let r2 = &st;

    let r3 = &mut st;

    println!("{},{},{}",r1,r2,r3)

}

悬空引用 Dangling References

悬空指针(Dangling Pointer) :一个指针引用了内存中的某个地址,而这块内存可能已经释放并分配给其它人使用了。

在Rust里,编译器可保证引用永远都不是悬空引用:
一如果你引用了某些数据,编译器将保证在引用离开作用域之前数据不会离开作用域

fn main() {
    let s = dangle();
}

fn dangle() ->&String {
    let st = String::from("我爱海鲸");
    &st
}

这里它在编译时期就会报错,那是因为st在离开dangle函数的时候就已经失效了,但是这个函数有返回了一个引用,那么这个引用指向的内存空间就是被释放后的内存空间,这样就形成了悬垂引用

我们可以看一下这个报错:缺少一个生命周期的声明符

引用的规则

   在任何给定的时刻,只能满足下列条件之一:

   一个可变的引用
   ―任意数量不可变的引用

引用必须一直有效

你好:我的2025

上一篇:Rust的所有权

下一篇:Rust的切片