闭包捕获变量的三种方式及示例
- 按值捕获(
move
语义):
- 解释:闭包获取变量的所有权,当闭包被调用时,变量的所有权被转移到闭包内部。闭包调用后,外部变量不可再使用。
- 示例:
fn main() {
let num = 5;
let closure = move || {
println!("The number is: {}", num);
};
// println!("The number is: {}", num); // 这行会报错,因为num的所有权已被闭包获取
closure();
}
- 按可变引用捕获:
- 解释:闭包获取变量的可变引用,允许闭包修改外部变量。外部作用域在闭包存活期间不能再获取该变量的可变引用,以避免数据竞争。
- 示例:
fn main() {
let mut num = 5;
let closure = || {
num += 1;
println!("The number is: {}", num);
};
closure();
println!("The number is: {}", num);
}
- 按不可变引用捕获:
- 解释:闭包获取变量的不可变引用,闭包内部只能读取该变量,不能修改。多个闭包可以同时按不可变引用捕获同一个变量。
- 示例:
fn main() {
let num = 5;
let closure = || {
println!("The number is: {}", num);
};
closure();
println!("The number is: {}", num);
}
不同捕获方式在实际应用场景中的区别
- 按值捕获:
- 适用场景:当你希望闭包拥有变量的所有权,并且不希望外部代码再访问或修改该变量时使用。例如,在将闭包传递给另一个线程时,因为线程需要独立拥有数据,所以需要按值捕获变量,确保数据的安全性和独立性。
- 按可变引用捕获:
- 适用场景:当闭包需要修改外部变量,同时又不想转移变量的所有权时使用。常用于需要在闭包内对共享状态进行更新的场景,比如在迭代器的
for_each
方法中,对每个元素进行修改,而这些元素又属于同一个外部可变集合。
- 按不可变引用捕获:
- 适用场景:当闭包只需要读取外部变量的值,并且可能会有多个闭包同时读取该变量时使用。比如在一些数据统计的闭包中,闭包只需要读取数据,多个闭包可以并发地读取同一个不可变数据,提高程序的执行效率。