喜欢的话别忘了点赞、收藏加关注哦(加关注即可阅读全文),对接下来的教程有兴趣的可以关注专栏。谢谢喵!(=^・ω・^=)
15.4.1. Drop
trait的意义
类型如果实现了Drop
trait,就可以让程序员自定义当值离开作用域时发生的操作。例如文件、网络资源的释放等。
在某些语言中(比如C/C++),对于某些类型,程序员每次使用完这些类型的实例时都必须写代码来释放内存或资源。如果忘记了,系统可能会过载并崩溃。在Rust中,程序员可以指定每当值超出范围时运行特定的代码,编译器将自动插入此代码。
任何类型都可以实现Drop
trait,而Drop
trait只要求实现drop
方法,其参数是对self
的可变引用。Drop
trait在预导入模块(prelude),所以说使用它时不需要手动地引入。看个例子:
rust
struct CustomSmartPointer {
data: String,
}
impl Drop for CustomSmartPointer {
fn drop(&mut self) {
println!("Dropping CustomSmartPointer with data `{}`!", self.data);
}
}
fn main() {
let c = CustomSmartPointer {
data: String::from("my stuff"),
};
let d = CustomSmartPointer {
data: String::from("other stuff"),
};
println!("CustomSmartPointers created.");
}
- 结构体
CustomSmartPointer
下有data
字段,为String
类型。 - 通过
impl Drop for CustomSmartPointer
为CustomSmartPointer
实现了Drop
trait。在其里面实现drop
方法,参数是&mut self
。这个方法通常是用于释放资源的,但出于演示的目的,这个方法里就只打印了一句话,把self
里的data
字段的数据打印出来。 - 在
main
函数里创建了两个CustomSmartPointer
的实例:c
存的是"my stuff",d
存的是other stuff
。最后打印"CustomSmartPointers created."。
输出:
CustomSmartPointers created.
Dropping CustomSmartPointer with data `other stuff`!
Dropping CustomSmartPointer with data `my stuff`!
程序会先打印main
函数的println!
的内容,也就是"CustomSmartPointers created."。由于c
和d
走出作用域都在第19行花括号后,所以程序接着会分别对c
和d
调用drop
函数。在实现Drop
trait时定义的drop
函数是打印一句话,所以这里c
和d
就会分别打印一句话。
15.4.2. 使用std::mem::drop
来提前drop
值
比较遗憾的是,我们很难直接禁用自动的drop
功能,也没必要。因为Drop
trait的目的就是进行自动的释放处理逻辑。
此外,Rust不允许手动调用Drop
trait的drop
方法 。但是可以调用标准库的std::mem::drop
函数来提前drop
值,相当于提前调用了Drop
trait的drop
方法,它的参数是要丢弃的值。看个例子:
rust
struct CustomSmartPointer {
data: String,
}
impl Drop for CustomSmartPointer {
fn drop(&mut self) {
println!("Dropping CustomSmartPointer with data `{}`!", self.data);
}
}
fn main() {
let c = CustomSmartPointer {
data: String::from("my stuff"),
};
let d = CustomSmartPointer {
data: String::from("other stuff"),
};
drop(c);
println!("CustomSmartPointers created.");
}
在main
函数中手动使用drop
函数把c
清理掉,而d
还是自动清理的,这个时候的输出顺序应该是c
在d
前。
输出:
Dropping CustomSmartPointer with data `my stuff`!
CustomSmartPointers created.
Dropping CustomSmartPointer with data `other stuff`!
这里有些人可能会提出疑问:c
在走出作用域之前就被释放了,那么在走出作用域后编译器会不会再调用一次drop
方法导致二次释放 (double free)的错误呢?答案是不会,Rust的设计很安全,它的所有权系统会保证引用的有效,而drop
也只会在确定不再使用这个值时被调用1次。