本文简要介绍rust语言中 Trait std::ops::Drop
的用法。
用法
pub trait Drop {
fn drop(&mut self);
}
析构函数中的自定义代码。
当不再需要某个值时,Rust 会对该值运行“destructor”。不再需要某个值的最常见方式是当它超出范围时。析构函数可能仍然在其他情况下运行,但我们将重点关注此处示例的范围。要了解其他一些情况,请参阅有关析构函数的 the reference 部分。
这个析构函数由两个组件组成:
- 如果为它的类型实现了这个特殊的
Drop
特征,则调用该值的Drop::drop
。 - 自动生成的“drop glue” 递归调用该值的所有字段的析构函数。
由于 Rust 会自动调用所有包含字段的析构函数,因此在大多数情况下您不必实现 Drop
。但是在某些情况下它很有用,例如对于直接管理资源的类型。该资源可能是内存,可能是文件说明符,也可能是网络套接字。一旦不再使用该类型的值,它应该通过释放内存或关闭文件或套接字来“clean up” 其资源。这是析构函数的工作,因此也是 Drop::drop
的工作。
例子
要查看析构函数的作用,让我们看一下以下程序:
struct HasDrop;
impl Drop for HasDrop {
fn drop(&mut self) {
println!("Dropping HasDrop!");
}
}
struct HasTwoDrops {
one: HasDrop,
two: HasDrop,
}
impl Drop for HasTwoDrops {
fn drop(&mut self) {
println!("Dropping HasTwoDrops!");
}
}
fn main() {
let _x = HasTwoDrops { one: HasDrop, two: HasDrop };
println!("Running!");
}
Rust 将首先为 _x
调用 Drop::drop
,然后为 _x.one
和 _x.two
调用,这意味着运行它会打印
Running!
Dropping HasTwoDrops!
Dropping HasDrop!
Dropping HasDrop!
即使我们删除了 HasTwoDrop
的 Drop
的实现,它的字段的析构函数仍然被调用。这将导致
Running!
Dropping HasDrop!
Dropping HasDrop!
您不能自己调用Drop::drop
因为Drop::drop
用于清理一个值,所以在调用该方法后使用该值可能很危险。由于 Drop::drop
不获取其输入的所有权,Rust 通过不允许您直接调用 Drop::drop
来防止滥用。
换句话说,如果你试图在上面的例子中显式调用Drop::drop
,你会得到一个编译器错误。
如果你想显式调用一个值的析构函数,可以使用 mem::drop
。
下单
不过,我们的两个 HasDrop
中哪一个先掉落?对于结构体,其声明顺序相同:首先是 one
,然后是 two
。如果您想自己尝试一下,可以修改上面的 HasDrop
以包含一些数据,例如整数,然后在 Drop
内部的 println!
中使用它。这种行为是由语言保证的。
与结构不同,局部变量以相反的顺序删除:
struct Foo;
impl Drop for Foo {
fn drop(&mut self) {
println!("Dropping Foo!")
}
}
struct Bar;
impl Drop for Bar {
fn drop(&mut self) {
println!("Dropping Bar!")
}
}
fn main() {
let _foo = Foo;
let _bar = Bar;
}
这将打印
Dropping Bar!
Dropping Foo!
完整规则请参阅the reference。
Copy
和 Drop
是互斥的
您不能在同一类型上同时实现 Copy
和 Drop
。 Copy
的类型会被编译器隐式复制,因此很难预测析构函数何时以及多久执行一次。因此,这些类型不能有析构函数。
相关用法
- Rust Drain.as_slice用法及代码示例
- Rust Drain.as_str用法及代码示例
- Rust DrainFilter用法及代码示例
- Rust Drain用法及代码示例
- Rust DirBuilder.new用法及代码示例
- Rust DirEntry.metadata用法及代码示例
- Rust Duration.as_micros用法及代码示例
- Rust Duration.subsec_nanos用法及代码示例
- Rust DebugList.entries用法及代码示例
- Rust Duration.checked_add用法及代码示例
- Rust DoubleEndedIterator.try_rfold用法及代码示例
- Rust Div用法及代码示例
- Rust DirBuilder.recursive用法及代码示例
- Rust Duration.new用法及代码示例
- Rust DerefMut用法及代码示例
- Rust DirBuilder.create用法及代码示例
- Rust DebugList用法及代码示例
- Rust DirEntry.path用法及代码示例
- Rust DebugMap.key用法及代码示例
- Rust Duration.subsec_micros用法及代码示例
- Rust DoubleEndedIterator.rfold用法及代码示例
- Rust DirEntry.file_type用法及代码示例
- Rust Duration.mul_f64用法及代码示例
- Rust DebugStruct.finish_non_exhaustive用法及代码示例
- Rust DebugStruct.field用法及代码示例
注:本文由纯净天空筛选整理自rust-lang.org大神的英文原创作品 Trait std::ops::Drop。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。