使用 Drop
特征在清理时运行代码
对智能指针模式很重要的第二个特征是 ,它允许
您可以自定义当值即将超出范围时发生的情况。您可以
为任何类型的 trait 提供实现,并且该代码可以
用于释放文件或网络连接等资源。Drop
Drop
我们在智能指针的上下文中引入,因为
在实现 trait 的
智能指针。例如,当 a 被丢弃时,它将释放
box 指向的堆上的空间。Drop
Drop
Box<T>
在某些语言中,对于某些类型,程序员必须调用代码来释放内存 或 resources。例子 包括文件句柄、套接字或锁。如果他们忘记了,系统可能会 变得超负荷并崩溃。在 Rust 中,你可以指定特定的 每当值超出范围时运行代码,编译器将 此代码自动。因此,您无需小心 将清理代码放置在程序中任何位置的特定 type 已完成 - 您仍然不会泄漏资源!
通过实现 trait,您可以指定要在值超出范围时运行的代码。该 trait 要求您实现一个名为 的方法,该方法采用对 .要查看 Rust 何时调用 ,
现在让我们实现 With 语句。Drop
Drop
drop
self
drop
drop
println!
示例 15-14 显示了一个结构体,其唯一的自定义
功能是,它将在
实例超出范围,以显示 Rust 何时运行函数。CustomSmartPointer
Dropping CustomSmartPointer!
drop
文件名: src/main.rs
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."); }
示例 15-14:一个 CustomSmartPointer
结构体
实现 Drop
trait,我们将把清理代码放到这个位置
该 trait 包含在 prelude 中,因此我们不需要将其引入
范围。我们在 上实现 trait 并提供一个
调用的方法的实现。函数的主体是放置要运行的任何逻辑的位置
类型的实例超出范围。我们在此处打印一些文本以
直观地演示 Rust 何时调用 .Drop
Drop
CustomSmartPointer
drop
println!
drop
drop
在 中,我们创建 的两个实例,然后打印 。在 的末尾,我们的实例将超出范围,Rust 将调用我们放置
在 Method 中,打印我们的最终消息。请注意,我们不需要
显式调用该方法。main
CustomSmartPointer
CustomSmartPointers created
main
CustomSmartPointer
drop
drop
当我们运行这个程序时,我们将看到以下输出:
$ cargo run
Compiling drop-example v0.1.0 (file:///projects/drop-example)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.60s
Running `target/debug/drop-example`
CustomSmartPointers created.
Dropping CustomSmartPointer with data `other stuff`!
Dropping CustomSmartPointer with data `my stuff`!
当我们的实例超出范围时,Rust 会自动调用我们,
调用我们指定的代码。变量的删除顺序与
他们的创造,所以在 .此示例的目的是
为您提供该方法如何工作的视觉指南;通常你会
指定您的类型需要运行的清理代码,而不是 print
消息。drop
d
c
drop
使用 std::mem::d rop
提前删除值
不幸的是,禁用自动功能并不简单。禁用通常不是必需的;trait 的全部意义在于它会自动得到处理。然而,偶尔,
您可能希望尽早清理值。一个例子是使用 smart
管理锁的指针:您可能希望强制
释放锁,以便同一范围内的其他代码可以获取锁。
Rust 不允许你手动调用 trait 的方法;相反
您必须调用 Standard Library 提供的函数
如果要强制在其范围结束之前删除值。drop
drop
Drop
drop
Drop
drop
std::mem::drop
如果我们尝试通过修改示例 15-14 中的函数来手动调用 trait 的方法,如示例 15-15 所示,我们将得到一个
编译器错误:Drop
drop
main
文件名: src/main.rs
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("some data"),
};
println!("CustomSmartPointer created.");
c.drop();
println!("CustomSmartPointer dropped before the end of main.");
}
示例 15-15:尝试从
Drop
trait 以尽早清理
当我们尝试编译此代码时,我们将收到此错误:
$ cargo run
Compiling drop-example v0.1.0 (file:///projects/drop-example)
error[E0040]: explicit use of destructor method
--> src/main.rs:16:7
|
16 | c.drop();
| ^^^^ explicit destructor calls not allowed
|
help: consider using `drop` function
|
16 | drop(c);
| +++++ ~
For more information about this error, try `rustc --explain E0040`.
error: could not compile `drop-example` (bin "drop-example") due to 1 previous error
此错误消息指出,不允许我们显式调用 .这
错误消息使用术语 Destructor,这是通用的编程术语
对于清理实例的函数。析构函数类似于创建实例的构造函数。Rust 中的函数是一个
特定的析构函数。drop
drop
Rust 不允许我们显式调用,因为 Rust 仍然会
自动调用 末尾的值。这将导致 double free 错误,因为 Rust 会尝试清理相同的值
两次。drop
drop
main
我们不能禁用 when a value out of 的自动插入
范围,并且我们不能显式调用该方法。所以,如果我们需要强制
一个要提前清理的值,我们使用该函数。drop
drop
std::mem::drop
该函数与 trait 中的方法不同。我们通过将要强制 drop 的值作为参数传递来调用它。
该函数位于 prelude 中,因此我们可以在示例 15-15 中修改为
调用函数,如示例 15-16 所示:std::mem::drop
drop
Drop
main
drop
文件名: src/main.rs
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("some data"), }; println!("CustomSmartPointer created."); drop(c); println!("CustomSmartPointer dropped before the end of main."); }
示例 15-16:显式调用 std::mem::d rop
在值超出范围之前删除值
运行此代码将打印以下内容:
$ cargo run
Compiling drop-example v0.1.0 (file:///projects/drop-example)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.73s
Running `target/debug/drop-example`
CustomSmartPointer created.
Dropping CustomSmartPointer with data `some data`!
CustomSmartPointer dropped before the end of main.
打印文本
,表示方法 code 被调用
在那个点下降。Dropping CustomSmartPointer with data `some data`!
CustomSmartPointer created.
CustomSmartPointer dropped before the end of main.
drop
c
您可以通过多种方式使用 trait 实现中指定的代码来
使清理方便和安全:例如,您可以使用它来创建您的
自己的内存分配器!使用 trait 和 Rust 的所有权系统,您可以
不必记得清理,因为 Rust 会自动进行清理。Drop
Drop
您也不必担心因意外而导致的问题
清理仍在使用的值:确保 OWNERSHIP SYSTEM
references are always valid 还确保 that 在
该值不再被使用。drop
现在我们已经研究了 smart 的一些特征
pointers,让我们看看标准
图书馆。Box<T>
本文档由官方文档翻译而来,如有差异请以官方英文文档(https://doc.rust-lang.org/)为准