ManuallyDrop 把「什么时候 drop」的决定权交还给你。这篇用带打印的 Drop 验证它的行为,并用三个典型场景(改 drop 顺序、从 Drop 类型里取出字段、拆装 Vec)说明它为什么存在。
编译:成功
运行(退出码 0):
size_of::<Noisy>() = 16 size_of::<ManuallyDrop<Noisy>>() = 16
作用域结束:ManuallyDrop<Noisy(忘记)> 不会 drop(下面不会有它的 drop 行)
通过 Deref 使用内部值:手动
Noisy(手动) drop
ManuallyDrop::drop 之后
into_inner 取回所有权,恢复正常 drop 规则:
Noisy(取出) dropDrop 的规则见Drop Trait 与资源释放。
编译:成功
运行(退出码 0):
默认:先 first,后 second
Noisy(first) drop
Noisy(second) drop
用 ManuallyDrop 反过来:先 second,后 first
Noisy(second) drop
Noisy(first) drop 源码:
1 | struct Guard { data: String }
2 | impl Drop for Guard { fn drop(&mut self) {} }
3 | fn main() { let g = Guard { data: "x".into() }; let s = g.data; println!("{}", s); }
编译:失败
error[E0509]: cannot move out of type `Guard`, which implements the `Drop` trait
--> <实验目录>/src/u119c.rs:3:57
|
3 | fn main() { let g = Guard { data: "x".into() }; let s = g.data; println!("{}", s); }
| ^^^^^^
| |
| cannot move out of here
| move occurs because `g.data` has type `String`, which does not implement the `Copy` trait
|
help: consider borrowing here
|
3 | fn main() { let g = Guard { data: "x".into() }; let s = &g.data; println!("{}", s); }
| +
help: consider cloning the value if the performance cost is acceptable
|
3 | fn main() { let g = Guard { data: "x".into() }; let s = g.data.clone(); println!("{}", s); }
| ++++++++
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0509`.
编译:成功
运行(退出码 0):
into_data 取出 "payload";Guard 自己的 Drop 没有运行(没有上一行的输出)
Guard::drop 运行了,会 drop 内部的 String 编译:成功
运行(退出码 0):
拆出 ptr / len = 4 / cap = 4;原 Vec 被 ManuallyDrop 包着,不会自动释放缓冲区
from_raw_parts 重新组装:[1, 2, 3, 4](缓冲区只会被释放一次)未初始化内存见MaybeUninit。
编译:成功
运行(退出码 0):
ManuallyDrop 之后还能读: ManuallyDrop
Noisy(ManuallyDrop) drop
forget 之后值没法再用、也没法再 drop;ManuallyDrop 可以