面试题答案
一键面试所有权转移问题举例
fn process_args(args: Vec<String>) {
// 这里 `args` 的所有权被转移进了函数
for arg in args {
println!("Processing argument: {}", arg);
}
}
fn main() {
let mut my_args = Vec::new();
my_args.push(String::from("first"));
my_args.push(String::from("second"));
process_args(my_args);
// 这里尝试使用 `my_args` 会报错,因为所有权已转移到 `process_args` 函数中
// println!("{:?}", my_args);
}
解决方案
可以使用 &mut
引用传递可变参数,而不转移所有权:
fn process_args(args: &mut Vec<String>) {
for arg in args.iter_mut() {
println!("Processing argument: {}", arg);
}
}
fn main() {
let mut my_args = Vec::new();
my_args.push(String::from("first"));
my_args.push(String::from("second"));
process_args(&mut my_args);
println!("{:?}", my_args);
}
确保可变参数在有效生命周期内正确运行
- 生命周期标注:当函数签名涉及引用时,明确标注生命周期。例如:
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}
- 借用规则:遵循Rust的借用规则,即同一时间内,要么只能有一个可变引用(可写),要么可以有多个不可变引用(可读),但不能同时存在可变和不可变引用。这可以防止数据竞争和悬垂指针问题。
- 作用域控制:确保引用在其关联数据的生命周期内有效。当数据被释放时,确保没有引用指向它。例如,不要从函数返回局部变量的引用:
// 错误示例
fn bad_function() -> &String {
let s = String::from("test");
&s
}
通过遵循这些原则,可以有效避免悬垂指针等问题,确保可变参数在其有效生命周期内正确运行。