所有权
所有权的规则 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)