rust - 如何从实现 Drop 的结构中移动类型未实现 Default 的字段?
问题描述
有一些类似的 问题,但答案需要该 字段实现或以某种方式使用该字段的类型初始化另一个值。Default
我们有一个Node
类型value
为T
:
struct Node<T> {
value: T,
next: Option<Box<T>>
}
它有一个value
从 a移动的方法Node
:
impl<T> Node<T> {
fn value(self) -> T {
self.value
}
}
上面的代码编译。但是如果我们Drop
实现Node
:
impl<T> Drop for Node<T> {
fn drop(&mut self) {}
}
然后我们会得到一个编译错误:
error[E0509]: cannot move out of type `Node<T>`, which implements the `Drop` trait
| self.value
| ^^^^^^^^^^
| |
| cannot move out of here
| move occurs because `self.value` has type `T`, which does not implement the `Copy` trait
我猜它不会编译,因为如果我们实现一个 custom Drop
,我们需要确保如果 drop 发生在方法块value
的末尾,则不要删除字段。value
但是,我们无法检查;即使我们可以,编译器也不能静态地检查我们是否这样做了。
解决此问题的一种方法是将value
字段存储为Option<T>
. Option
但是假设由于某些原因(开销等)我们不想使用,
我们还能做些什么来同时拥有自定义Drop
和value
移动value
字段的方法?
我想我们必须使用一些unsafe
方法,这很好。
解决方案
我不知道不使用的方法unsafe
(尽管其他人可能),但这是一种使用方法unsafe
:
use std::{ptr, mem};
impl<T> Node<T> {
fn value(mut self) -> T {
unsafe {
let v: T = ptr::read(&self.value);
ptr::drop_in_place(&mut self.next);
mem::forget(self);
v
}
}
}
我们使用ptr::read
将所需的值移出。然后我们需要使用mem::forget
onNode
来确保它的drop
方法没有被调用(否则value
可能会被丢弃两次并导致未定义的行为)。为了防止next
成员泄漏,我们使用ptr::drop_in_place
运行它的drop
方法。
有趣的是,这个安全代码不起作用:
impl<T> Node<T> {
fn value(self) -> T {
match self {
Node {value, next: _} => value
}
}
}
它给出了同样的错误:
error[E0509]: cannot move out of type
Node<T>
,实现了Drop
trait
我本来希望match
表达式拥有所有的所有权self
并将其分解为它的组件,就没有办法drop
被调用self
,因此编译器也没有理由抱怨。但显然它不是这样工作的。
推荐阅读
- swift - 字典未存储在 UserDefaults 上
- python-3.x - 在 Pandas `transform()` 中使用自定义函数(中值绝对偏差)
- google-apps-script - 是否可以单独获取每个单词的文本样式?
- angular - 动态图像未在移动设备上加载 - Angular
- python - Python:使用两个变量字符串作为 Regex.findall 标准
- javascript - scss/css动态内容
- java - Android youtube 提取器库在响应时返回 null
- flutter - 使用来自另一个类的实例访问有状态小部件的变量时,在 null 上调用 getter 长度
- php - 此代码适用于 php 5.6(服务器状态),为什么它不适用于 php 7.4?
- api - Flutter OCR - 谷歌云视觉 API