面试题答案
一键面试所有权概念
- 定义:Rust的所有权系统是其内存管理的核心机制。每个值在Rust中都有一个变量,称为该值的所有者。当所有者离开其作用域时,该值将被释放。
- 规则:
- 每个值都有一个唯一的所有者。
- 当所有者离开作用域时,值被丢弃。
- 示例:
fn main() {
let s = String::from("hello"); // s 是 "hello" 的所有者
// s 的作用域在此处结束,"hello" 会被释放
}
借用概念
- 定义:借用允许你在不获取所有权的情况下使用值。有两种类型的借用:不可变借用(
&T
)和可变借用(&mut T
)。 - 规则:
- 同一时间,你可以有任意数量的不可变借用或一个可变借用。
- 借用的作用域不能超过所有者的作用域。
- 示例:
fn main() {
let s = String::from("hello");
let len = calculate_length(&s); // 不可变借用
println!("The length of '{}' is {}.", s, len);
let mut s1 = String::from("world");
change(&mut s1); // 可变借用
println!("s1 is now {}", s1);
}
fn calculate_length(s: &String) -> usize {
s.len()
}
fn change(s: &mut String) {
s.push_str(", world");
}
避免因所有权和借用规则导致错误的方法
- 理解作用域:确保借用的作用域合理,避免在借用的值超出其所有者作用域后仍使用借用。例如:
fn main() {
let s;
{
let temp = String::from("test");
s = &temp; // 错误,temp离开作用域后,s成为悬垂引用
}
// 使用 s 会导致未定义行为
}
正确做法是让所有者的作用域覆盖借用的使用:
fn main() {
let temp = String::from("test");
let s = &temp;
println!("{}", s);
}
- 遵循借用规则:避免同时存在可变借用和不可变借用。例如:
fn main() {
let mut data = String::from("rust");
let r1 = &data; // 不可变借用
let r2 = &mut data; // 错误,同一时间不能有不可变和可变借用
println!("{} {}", r1, r2);
}
正确做法是先结束不可变借用,再进行可变借用:
fn main() {
let mut data = String::from("rust");
{
let r1 = &data;
println!("{}", r1);
}
let r2 = &mut data;
r2.push_str(" rules");
println!("{}", r2);
}
- 使用生命周期标注:在函数或结构体中使用泛型时,明确生命周期参数,确保借用的生命周期合理。例如:
struct Container<'a> {
value: &'a i32
}
fn main() {
let num = 42;
let container = Container { value: &num };
println!("{}", container.value);
}
通过'a
生命周期标注,确保container
中的借用value
不会超过num
的生命周期。