使用Drop
特性
对智能指针模式很重要的第二个特征是Drop
,这样就可以
您可以自定义当值即将超出范围时发生的情况。您可以
为Drop
trait 的 trait 中,那么该代码就可以
用于释放文件或网络连接等资源。
我们即将推出Drop
在智能指针的上下文中,因为
的功能Drop
trait 在实现
智能指针。例如,当Box<T>
被丢弃时,它将释放
box 指向的堆上的空间。
在某些语言中,对于某些类型,程序员必须调用代码来释放内存 或 resources。例子 包括文件句柄、套接字或锁。如果他们忘记了,系统可能会 变得超负荷并崩溃。在 Rust 中,你可以指定特定的 每当值超出范围时运行代码,编译器将 此代码自动。因此,您无需小心 将清理代码放置在程序中任何位置的特定 type 已完成 - 您仍然不会泄漏资源!
您可以通过实现Drop
特性。这Drop
trait 要求您实现一个名为drop
它接受对self
.要查看 Rust 何时调用drop
,
让我们实现drop
跟println!
声明。
示例 15-14 显示了一个CustomSmartPointer
struct 中唯一自定义的
功能是它将打印Dropping CustomSmartPointer!
当
实例超出范围,以显示 Rust 何时运行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
struct 的
实现Drop
trait 中放置清理代码的位置
这Drop
trait 包含在 Prelude 中,因此我们不需要将其引入
范围。我们实现Drop
trait 开启CustomSmartPointer
并提供
实现drop
调用println!
.主体drop
function 是放置任何要运行的 logic 的位置
类型的实例超出范围。我们在此处打印一些文本以
直观地演示 Rust 何时调用drop
.
在main
中,我们创建两个CustomSmartPointer
,然后打印CustomSmartPointers created
.在main
、我们的CustomSmartPointer
将超出范围,Rust 将调用我们放置
在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 自动调用drop
对我们来说,当我们的实例超出范围时,
调用我们指定的代码。变量的删除顺序与
他们的创造,所以d
之前被丢弃c
.此示例的目的是
为您提供一个直观的指南,让您了解如何drop
方法有效;通常你会
指定您的类型需要运行的清理代码,而不是 print
消息。
提前删除值std::mem::drop
不幸的是,禁用自动drop
功能性。禁用drop
通常不是必需的;的重点Drop
trait 是它会自动处理。然而,偶尔,
您可能希望尽早清理值。一个例子是使用 smart
管理锁的指针:您可能希望强制drop
方法,该
释放锁,以便同一范围内的其他代码可以获取锁。
Rust 不允许你调用Drop
trait 的drop
方法;相反
您必须调用std::mem::drop
标准库提供的函数
如果要强制在其范围结束之前删除值。
如果我们尝试调用Drop
trait 的drop
方法,方法是修改main
函数,如示例 15-15 所示,我们将得到一个
编译器错误:
文件名: 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
method 从
这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
此错误消息指出,不允许我们显式调用drop
.这
错误消息使用术语 Destructor,这是通用的编程术语
对于清理实例的函数。析构函数类似于创建实例的构造函数。这drop
function 是一个
特定的析构函数。
Rust 不允许我们调用drop
因为 Rust 仍然会
自动调用drop
在main
.这将导致 double free 错误,因为 Rust 会尝试清理相同的值
两次。
我们不能禁用drop
当值超出
范围,我们不能调用drop
方法。所以,如果我们需要强制
一个值,我们使用std::mem::drop
功能。
这std::mem::drop
函数与drop
方法中的Drop
特性。我们通过将要强制 drop 的值作为参数传递来调用它。
函数在 prelude 中,因此我们可以修改main
在示例 15-15 中为
调用drop
函数,如示例 15-16 所示:
文件名: 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::drop
显式
在值超出范围之前删除值
运行此代码将打印以下内容:
$ 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.
文本Dropping CustomSmartPointer with data `some data`!
已打印
在CustomSmartPointer created.
和CustomSmartPointer dropped before the end of main.
文本,显示drop
方法代码被调用到
落c
在那个时候。
您可以使用在Drop
trait 实现以多种方式实现
使清理方便和安全:例如,您可以使用它来创建您的
自己的内存分配器!使用Drop
trait 和 Rust 的所有权系统,你
不必记得清理,因为 Rust 会自动进行清理。
您也不必担心因意外而导致的问题
清理仍在使用的值:确保 OWNERSHIP SYSTEM
references are always valid 还确保drop
在以下情况下仅调用一次
该值不再被使用。
现在我们已经检查了Box<T>
以及 smart 的一些特性
pointers,让我们看看标准
图书馆。
本文档由官方文档翻译而来,如有差异请以官方英文文档(https://doc.rust-lang.org/)为准