简介
在Rust中,所有权是一种管理内存的方式,它保证了内存安全和性能。通过一个简单而强大的概念——所有权,Rust避免了常见的错误,如空指针、悬垂指针和数据竞争等。
所有权规则
- 每个值都有一个变量作为其所有者。
- 同一时间只能有一个所有者。
- 当所有者超出范围,值将被释放。
所有权和函数
在Rust中,将值传递给函数类似于赋值给变量:
fn main() {
let s = String::from("hello"); // s来到了作用域
takes_ownership(s); // s的值被移动到了函数中,所以无法再使用s
// 在此处尝试使用s会导致编译错误
} // 这里,s离开作用域并调用`drop`方法。由于s的值已被移动,所以没有要释放的东西。
fn takes_ownership(some_string: String) { // some_string来到了作用域
println!("{}", some_string);
} // 这里,some_string离开作用域并调用`drop`方法。内存被释放
借用和引用
为了使函数使用值但不取得所有权,我们可以使用引用 &
:
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是对String的引用
s.len()
} // 这里,s离开了作用域。但因为它没有所有权,所以什么也不会发生
可变引用
如果你想修改借用的值,就需要使用可变引用 &mut
:
fn main() {
let mut s = String::from("hello");
change(&mut s);
}
fn change(s: &mut String) {
s.push_str(", world");
}
悬垂引用
Rust编译器会确保引用永远不会指向无效的数据:
fn main() {
let reference_to_nothing = dangle(); // error!
}
fn dangle() -> &String { // dangle返回一个字符串的引用
let s = String::from("hello"); // s在这里被创建
&s // 返回字符串s的引用
} // 这里,s离开作用域并被丢弃。其内存被释放。
总结
Rust的所有权概念可能看起来有些复杂,但它是Rust强大而安全的根基。一旦你理解了这些规则,就可以在不牺牲性能或内存安全的情况下编写更加高效和安全的代码。