|
|
|
@ -43,20 +43,22 @@ impl Drop for Foo {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
|
let _x = HasTwoDrops { two: HasDrop2 ,one: HasDrop1,};
|
|
|
|
|
let _x = HasTwoDrops {
|
|
|
|
|
two: HasDrop2,
|
|
|
|
|
one: HasDrop1,
|
|
|
|
|
};
|
|
|
|
|
let _foo = Foo;
|
|
|
|
|
println!("Running!");
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
上面代码虽然长,但是目的其实很单纯,就是为了观察不同情况下的`Drop`,变量级别的、结构体内部字段的, 有几点值得注意:
|
|
|
|
|
上面代码虽然长,但是目的其实很单纯,就是为了观察不同情况下变量级别的、结构体内部字段的 `Drop`,有几点值得注意:
|
|
|
|
|
|
|
|
|
|
- `Drop` 特征中的 `drop` 方法借用了目标的可变引用,而不是拿走了所有权,这里先设置一个悬念,后边会讲
|
|
|
|
|
- 结构体中每个字段都有自己的 `Drop`
|
|
|
|
|
|
|
|
|
|
来看看输出:
|
|
|
|
|
来看看输出:
|
|
|
|
|
```console
|
|
|
|
|
Running!
|
|
|
|
|
Dropping Foo!
|
|
|
|
@ -70,8 +72,8 @@ Dropping HasDrop2!
|
|
|
|
|
#### Drop 的顺序
|
|
|
|
|
观察以上输出,我们可以得出以下关于 `Drop` 顺序的结论
|
|
|
|
|
|
|
|
|
|
- **变量级别,按照逆序的方式**,`_x`在`_foo`之前创建,因此`_x`在`_foo`之后被drop
|
|
|
|
|
- **结构体内部,按照顺序的方式**, 结构体`_x`中的字段按照定义中的顺序依次`drop`
|
|
|
|
|
- **变量级别,按照逆序的方式**,`_x` 在 `_foo` 之前创建,因此 `_x` 在 `_foo` 之后被 `drop`
|
|
|
|
|
- **结构体内部,按照顺序的方式**,结构体 `_x` 中的字段按照定义中的顺序依次 `drop`
|
|
|
|
|
|
|
|
|
|
#### 没有实现 Drop 的结构体
|
|
|
|
|
实际上,就算你不为 `_x` 结构体实现 `Drop` 特征,它内部的两个字段依然会调用 `drop`,移除以下代码,并观察输出:
|
|
|
|
@ -83,7 +85,7 @@ impl Drop for HasTwoDrops {
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
原因在于,Rust自动为几乎所有类型都实现了`Drop`特征,因此就算你不手动为结构体实现`Drop`,它依然会调用默认实现的`drop`函数,同时再调用每个字段的`drop`方法,最终打印出:
|
|
|
|
|
原因在于,Rust 自动为几乎所有类型都实现了 `Drop` 特征,因此就算你不手动为结构体实现 `Drop`,它依然会调用默认实现的 `drop` 函数,同时再调用每个字段的 `drop` 方法,最终打印出:
|
|
|
|
|
```cnosole
|
|
|
|
|
Dropping HasDrop1!
|
|
|
|
|
Dropping HasDrop2!
|
|
|
|
@ -91,7 +93,7 @@ Dropping HasDrop2!
|
|
|
|
|
|
|
|
|
|
## 手动回收
|
|
|
|
|
当使用智能指针来管理锁的时候,你可能希望提前释放这个锁,然后让其它代码能及时获得锁,此时就需要提前去手动 `drop`。
|
|
|
|
|
但是在之前我们提到一个悬念,就是`Drop::drop`只是借用了目标值的可变引用,就算你提前调用了该方法,但是后面的代码依然可以使用目标值,这就会访问一个并不存在的值,非常不安全,好在Rust会阻止你:
|
|
|
|
|
但是在之前我们提到一个悬念,`Drop::drop` 只是借用了目标值的可变引用,所以,就算你提前调用了 `drop`,后面的代码依然可以使用目标值,但是这就会访问一个并不存在的值,非常不安全,好在 Rust 会阻止你:
|
|
|
|
|
```rust
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
struct Foo;
|
|
|
|
@ -121,7 +123,7 @@ error[E0040]: explicit use of destructor method
|
|
|
|
|
| help: consider using `drop` function: `drop(foo)`
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
如上所示,编译器直接阻止了我们调用`Drop`特征的`drop`方法,原因是该方法是析构函数,这是一个用来清理实例的通用编程概念,对于Rust而言,不允许显式的调用析构函数。好在在报错的同时,编译器还给出了一个提示:使用`drop`函数。
|
|
|
|
|
如上所示,编译器直接阻止了我们调用 `Drop` 特征的 `drop` 方法,原因是对于 Rust 而言,不允许显式地调用析构函数(这是一个用来清理实例的通用编程概念)。好在在报错的同时,编译器还给出了一个提示:使用 `drop` 函数。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
针对编译器提示的 `drop` 函数,我们可以大胆推测下:它能够拿走目标值的所有权。现在来看看这个猜测正确与否,以下是 `std::mem::drop` 函数的签名:
|
|
|
|
@ -167,7 +169,7 @@ impl Drop for Foo {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
以下代码报错如下:
|
|
|
|
|
以上代码报错如下:
|
|
|
|
|
```console
|
|
|
|
|
error[E0184]: the trait `Copy` may not be implemented for this type; the type has a destructor
|
|
|
|
|
--> src/main.rs:24:10
|
|
|
|
|