所有权
所有权规则
- Rust中的每一个值都有一个被称为其所有者的变量
- 值在任一时刻有且只有一个所有者。
- 当所有者(变量)离开作用域,这个值将被丢弃。
String类型
在 Rust 中声明string类型的变量需要这样操作
let s = String::from("hello"); // 声明
虽然string类型的数据都是被存放在堆中,但是复制string类型的变量和 JavaScript 不同,如果简单的赋值
let s1 = String::from("hello"); // 声明
let s2 = s1; // rust中称之为移动而不是复制
那么s1
就会自动被垃圾回收机制回收,因为s1
和s2
在栈中指向的是堆中同一个地址,所以如果s1
和s2
离开作用域,他们都会尝试释放相同的内存,这就会导致二次释放的错误,会导致内存污染和潜在的安全漏洞。
如果一定要复制,则可使用clone
let s1 = String::from("hello"); // 声明
let s2 = s1.clone();
引用和借用
只传递值而不传递所有权可以使用引用,比如
fn main() {
let s1 = String::from("hello");
let len = calculate_length(&s1); // 在变量前加一个&符号即表示引用,它们允许你使用值但不获取其所有权
println!("The length of '{}' is {}.", s1, len);
}
fn calculate_length(s: &String) -> usize {
s.len()
}
将创建一个引用的行为称为 借用(borrowing),函数使用引用的变量不可修改变量的值。
可变引用
允许函数修改变量的值 注意:在同一时间只能有一个对某一特定数据的可变引用,避免数据竞争 不能在拥有不可变引用的同时拥有可变引用
数据竞争由这三个行为造成:
- 两个或更多指针同时访问同一数据。
- 至少有一个指针被用来写入数据。
- 没有同步数据访问的机制。
在声明变量前添加 mut
即可,参数的位置也需要添加
fn main() {
let mut s = String::from("hello");
change(&mut s);
}
fn change(some_string: &mut String) {
some_string.push_str(", world");
}