Rust从入门到实战系列一百七十四:通过 std::mem::drop 提早丢弃值

不幸的是,我们并不能直截了当的禁用 drop 这个功能。通常也不需要禁用 drop ;整个 Drop trait 存在
的意义在于其是自动处理的。然而,有时你可能需要提早清理某个值。一个例子是当使用智能指针管理
锁时;你可能希望强制运行 drop 方法来释放锁以便作用域中的其他代码可以获取锁。Rust 并不允许我
们主动调用 Drop trait 的 drop 方法;当我们希望在作用域结束之前就强制释放变量的话,我们应该使
用的是由标准库提供的 std::mem::drop。
如果我们像是示例 15-14 那样尝试调用 Drop trait 的 drop 方法,就会得到像示例 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 trait 的 drop 方法提早清理
如果尝试编译代码会得到如下错误:
$ 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: drop(c)
For more information about this error, try rustc --explain E0040.
error: could not compile drop-example due to previous error
错误信息表明不允许显式调用 drop。错误信息使用了术语 析构函数(destructor),这是一个清理实例
的函数的通用编程概念。析构函数对应创建实例的 构造函数。Rust 中的 drop 函数就是这么一个析构函数。
Rust 不允许我们显式调用 drop 因为 Rust 仍然会在 main 的结尾对值自动调用 drop,这会导致一个
double free 错误,因为 Rust 会尝试清理相同的值两次。
因为不能禁用当值离开作用域时自动插入的 drop,并且不能显式调用 drop,如果我们需要强制提早清
理值,可以使用 std::mem::drop 函数。
std::mem::drop 函数不同于 Drop trait 中的 drop 方法。可以通过传递希望提早强制丢弃的值作为参
数。std::mem::drop 位于 prelude,所以我们可以修改示例 15-15 中的 main 来调用 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©;
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 [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 会自动考虑这些问题。
我们也无需担心意外的清理掉仍在使用的值,这会造成编译器错误:所有权系统确保引用总是有效的,
也会确保 drop 只会在值不再被使用时被调用一次。
现在我们学习了 Box 和一些智能指针的特性,让我们聊聊标准库中定义的其他几种智能指针。

  • 25
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值