【Rust】所有权、引用、借用

所有权

所有权的规则
1. Rust 中的每一个值都有一个被称为其 所有者(owner)的变量。
2. 值在任一时刻有且只有一个所有者。
3. 当所有者(变量)离开作用域,这个值将被丢弃。

Rust 采取了一个不同的策略:内存在拥有它的变量离开作用域后就被自动释放

变量与数据交互

方式(一):移动,转移所有权

let s1 = String::from("hello");
let s2 = s1;
// s1 不能再用

方式(二):克隆

let s1 = String::from("hello");
let s2 = s1.clone();
// s1,s2都可用

栈上的数据:复制
实现了Copy trait 整数、布尔、浮点、字符、元组

向函数传递值可能会移动或复制,移动时所有权会转移,复制不会转移
返回值也可以转移所有权

let mut s1 = String::from("hello");
s1 = take(s1);// 转移所有权到函数
println!("{}",s1);

fn take(s: String) -> String {
    s// 返回所有权
}

 

引用

&符号是引用,*符号是解引用
创建一个引用的行为称为 借用(borrowing)

不可变引用

let s = String::from("hello");// 不可变变量
let len = calculate_length(&s);// &s是指向s的引用,但是并不拥有它
fn calculate_length(s: &String) -> usize {// 不可变引用参数
    s.len()
}

可变引用

let mut s = String::from("hello");// 可变变量
change(&mut s);
fn change(s: &mut String) {// 可变引用参数
    s.push_str(", world");
}

限制:在同一时间只能有一个对某一特定数据的可变引用

// 情况一
let mut s = String::from("hello");// 可变变量
let r1 = &mut s;
let r2 = &mut s;
println!("{}, {}", r1, r2);// 报错 不能在同一时间多次将 s 作为可变变量借用

// 情况二
let mut s = String::from("hello");
let r1 = &s; // 没问题
let r2 = &s; // 没问题
let r3 = &mut s; // 大问题 不能在拥有不可变引用的同时拥有可变引用
println!("{}, {}, and {}", r1, r2, r3);

// 情况三
let mut s = String::from("hello");
let r1 = &s; // 没问题
let r2 = &s; // 没问题
println!("{} and {}", r1, r2);// 不可变引用 r1 和 r2 的作用域在 println! 最后一次使用之后结束
// 此位置之后 r1 和 r2 不再使用
let r3 = &mut s; // 没问题
println!("{}", r3);

这个限制的好处是 Rust 可以在编译时就避免数据竞争。
数据竞争(data race)类似于竞态条件,它可由这三个行为造成:
两个或更多指针同时访问同一数据。
至少有一个指针被用来写入数据。
没有同步数据访问的机制。

引用的规则
让我们概括一下之前对引用的讨论:
在任意给定时间,要么 只能有一个可变引用,要么 只能有多个不可变引用。
引用必须总是有效的。

 

借用

创建一个引用的行为称为 借用(borrowing)

posted @ 2022-01-08 20:57  翠微  阅读(249)  评论(0编辑  收藏  举报