面试题答案
一键面试在Rust中,闭包捕获变量有三种方式:按值捕获、按可变引用捕获和按不可变引用捕获。以下分别举例说明它们对变量所有权和生命周期的影响:
按值捕获
闭包通过move
语义按值捕获变量,这意味着变量的所有权被转移到闭包中。一旦闭包按值捕获了变量,外部作用域就不能再使用该变量。
fn main() {
let num = 5;
let closure = move || {
println!("The number is: {}", num);
};
// 这里不能再使用num,因为所有权已转移到闭包中
// println!("num: {}", num); // 这行会编译错误
closure();
}
在上述例子中,num
的所有权被转移到闭包closure
中,所以在闭包定义之后,num
在外部作用域不再可用。闭包的生命周期和num
的生命周期绑定在一起,只要闭包存在,num
就会一直存在。
按可变引用捕获
闭包可以按可变引用捕获变量,这样闭包可以修改捕获的变量。但在闭包捕获期间,外部作用域不能再使用该可变引用。
fn main() {
let mut num = 5;
let closure = || {
num += 1;
println!("The number is: {}", num);
};
// 这里不能再对num进行可变借用,因为闭包已经可变借用了num
// num += 2; // 这行会编译错误
closure();
println!("num: {}", num);
}
在这个例子中,闭包closure
按可变引用捕获了num
,因此在闭包定义之后,外部作用域不能再对num
进行可变借用。闭包的生命周期和对num
的可变借用的生命周期一致,只要闭包存在,这个可变借用就存在。
按不可变引用捕获
闭包可以按不可变引用捕获变量,闭包可以读取但不能修改捕获的变量。同时,外部作用域仍然可以使用该变量。
fn main() {
let num = 5;
let closure = || {
println!("The number is: {}", num);
};
println!("num: {}", num);
closure();
}
在这个例子中,闭包closure
按不可变引用捕获了num
,外部作用域仍然可以使用num
。闭包的生命周期和对num
的不可变借用的生命周期一致,只要闭包存在,这个不可变借用就存在。