借助Drop trait在清理时运行代码
前面我们学过,变量只在变量所在的作用域有效,离开了作用域,如果没有转移所有权的话,将被清理,Drop trait允许我们在变量离开作用域时执行某些自定义操作。
实现Drop trait
我们可以为我们的自定义类型实现Drop trait:
#[derive(Debug)]
struct CustomSmartPointer {
data: String,
}
impl Drop for CustomSmartPointer {
fn drop(&mut self) {
println!("删除带有数据的`{}`的CustomSmartPointer!", self.data);
}
}
drop函数将在作用域结束时调用:
fn run() {
let c = CustomSmartPointer { data: String::from("c") };
let d = CustomSmartPointer { data: String::from("d") };
println!("CustomSmartPointers创建完成.");
// 下面rust将自动调用:(调用顺序是根据变量声明顺序,后进先出)
d.drop()
c.drop()
}
run();
// CustomSmartPointers创建完成.
// 删除带有数据的`d`的CustomSmartPointer!
// 删除带有数据的`c`的CustomSmartPointer!
有时需要提前清理一个值。例如使用智能指针来管理锁时,强制运行drop方法来提前释放锁,从而允许同一作用域内的其他代码来获取它。
除了rust可以按上面规则自动清理变量,我们也可以使用drop函数手动清理:
fn run() {
let c = CustomSmartPointer { data: String::from("c") };
let d = CustomSmartPointer { data: String::from("d") };
println!("CustomSmartPointers创建完成.");
// 使用std::mem::drop提前清理值
use std::mem::drop;
drop(c);
// 清理之后将不能再使用
// println!("{:?}", c); // 报错,c已经被清理
println!("run函数调用完毕");
}
run();
// CustomSmartPointers创建完成.
// 删除带有数据的`c`的CustomSmartPointer!
// run函数调用完毕
// 删除带有数据的`d`的CustomSmartPointer!
由于c在run函数结束直接就已经被手动清理了,所以在run函数结束的时候只会清理d
有同学可能会想,是不是可以直接调用trait上的drop方法来清理数据呢?
fn run() {
let c = CustomSmartPointer { data: String::from("c") };
// 事实上rust并不允许手动调用Drop trait的drop方法
c.drop() // 报错
}
run();
Drop trait主要用来清理一些副作用,比如当变量被清理时我们需要取消正在进行的网络请求,关闭正在打开的文件等。