Rust 中的 Drop Trait
2019-08-10 16:08 rust
Drop Trait
先看代码:
#[derive(Default)]
struct Point {
pub x: i32,
pub y: i32,
}
#[derive(Default)]
struct Rectangle {
pub p1: Point,
pub p2: Point,
}
impl Drop for Point {
fn drop(&mut self) {
println!("Point {} {} ::drop()", self.x, self.y);
}
}
impl Drop for Rectangle {
fn drop(&mut self) {
println!("Rectangle::drop()");
}
}
fn main() {
let _p = Point::default();
let _r = Rectangle {
p1: Point { x: 1, y: 2 },
p2: Point { x: 3, y: 4 },
};
}
打印的结果是:
Rectangle::drop()
Point 1 2 ::drop()
Point 3 4 ::drop()
Point 0 0 ::drop()
可以发现 Drop Trait 的几个特性:
Drop::drop()方法是被隐式调用的.- 先调用了
Rectangle::drop(), 之后调用了其内部属性的Point::drop(). Rectangle内部性性的drop()方法是基于声明的先后顺序调用的. 上面才会先打印Point 1 2 ::drop(), 再打印Point 3 4 ::drop().- 先声明的变量后被
drop. 上面的试验, 先 drop 了Rectangle _r, 之后再 drop 了Point _p.
另外还有几个特点:
Drop::drop()是不能手动调用的.Droptrait 只能用于结构体 (struct), 不能用于 primative type.
mem::drop
尽管不能手动调用 Drop::drop() 方法来 destruct 一个结构体, 但我们可以调用
std::mem::drop() 函数, 这个函数的实现也是非常简单的.
#[inline]
fn drop(_x: T) { }
它获取了传入参数的所有权, 然后什么都不做, 等该函数运行完之后, 该变量 _x 的值
的生命周期已完成, 它就要被释放掉.
我们来修改一下上面的测试代码:
fn main() {
let p = Point::default();
let _r = Rectangle {
p1: Point { x: 1, y: 2 },
p2: Point { x: 3, y: 4 },
};
std::mem::drop(p);
}
这次的打印结果是:
Point 0 0 ::drop()
Rectangle::drop()
Point 1 2 ::drop()
Point 3 4 ::drop()
Point p 优先被 drop 了, 因为 std::mem::drop(p); 这条调用完结之后, Point p
的生命周期就完结了. 之后, 在 main() 函数结束时, 自动调用了 Rectangle _r 的 drop()
方法.
关于 mem::drop() 有一点要注意的是, 它只能用来 drop 没有实现 Copy trait 的变量,
像 rust 里的原始数据类型, usize/u8/u16/u32/u64/u128/... 这些都是实现了 Copy trait的,
mem::drop() 来 drop 它们时, 是没有效果的. 比如下面的代码, 变量 x 在传入 drop()
函数时, 它的值是被复制了一份的, 所以并不能 drop 变量 x 本身.
let x = 42;
std::mem::drop(x);