假设我有一个Rust struct
,它有一个析构函数:
pub struct D1 {
a: String,
b: String
}
impl Drop for D1 {
fn drop(&mut self) {
println!("{0}", self.a)
}
}
我想实现一个方法,将部分或全部字段移出对象,并在进程中销毁它。显然,如果对象的析构函数运行,这是不安全的--它将尝试不安全地读取被移动的字段。然而,如果析构函数被抑制,这应该是安全的。但我找不到一种方法来抑制析构函数,使移动安全。mem::forget
不起作用,因为编译器在处理析构函数时没有特别处理它:
impl D1 {
fn into_raw_parts(self) -> (String, String) {
let (a, b) = (self.a, self.b); // cannot move here
mem::forget(self);
(a, b)
}
}
ManuallyDrop
也不起作用-它只通过引用提供内部数据,防止移动:
一个二个一个一个
我大概可以通过研究unsafe
代码来解决这个问题,但我想知道是否有一种安全的方法来做到这一点--我是否错过了一些API或其他技术来告诉Rust我可以安全地移出一个值,因为我不打算运行析构函数?
1条答案
按热度按时间izj3ouym1#
在安全代码中,无法使实现
Drop
的类型保持未初始化状态,但是,可以使用伪值使其保持初始化状态:这将给
self
留下空字符串(甚至不分配任何内存)。当然,Drop
实现必须容忍这种情况,并且不做不希望的事情。如果真实的情况中的字段类型没有方便的占位符值,那么可以将字段设置为
Option
s。当Drop::drop()
本身需要移出self
时,这也是一种常用的技术。