How can I move a value out of the argument to Drop::drop()?
我正在使用
但是,
1 2 3 4 5 | error[E0509]: cannot move out of type `S`, which implements the `Drop` trait --> src/lib.rs:9:18 | 9 | destroyT(self.member) | ^^^^^^^^^^^ cannot move out of here |
似乎应该有办法解决这个问题,因为我目前在
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | struct T; struct S { member: T, } impl Drop for S { fn drop(&mut self) { destroyT(self.member) } } // elsewhere, in a library fn destroyT(t: T) { //... } |
最安全、最简单的方法是使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | struct T; impl Drop for T { fn drop(&mut self) { println!("dropping T"); } } struct S { member: Option< T >, } impl Drop for S { fn drop(&mut self) { if let Some(t) = self.member.take() { destroy_t(t); } } } fn destroy_t(_t: T) { println!("destroy T"); } fn main() { let _x = S { member: Some(T) }; } |
您可以选择使用带有
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | use std::mem::{self, ManuallyDrop}; struct T; impl Drop for T { fn drop(&mut self) { println!("dropping T"); } } struct S { member: ManuallyDrop< T >, } impl Drop for S { fn drop(&mut self) { unsafe { let valid_t = mem::replace(&mut *self.member, mem::uninitialized()); destroy_t(valid_t); // do *not* call ManuallyDrop::drop }; } } fn destroy_t(_t: T) { println!("destroy T"); } fn main() { let _x = S { member: ManuallyDrop::new(T), }; } |
1 使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | #![feature(maybe_uninit)] use std::mem::{self, ManuallyDrop, MaybeUninit}; struct T; impl Drop for T { fn drop(&mut self) { println!("dropping T"); } } struct S { member: ManuallyDrop<MaybeUninit< T >>, } impl Drop for S { fn drop(&mut self) { let invalid_t = MaybeUninit::uninitialized(); let valid_t = mem::replace(&mut *self.member, invalid_t); let valid_t = unsafe { valid_t.into_inner() }; destroy_t(valid_t); // do *not* call ManuallyDrop::drop } } fn destroy_t(_t: T) { println!("destroy T"); } fn main() { let _x = S { member: ManuallyDrop::new(MaybeUninit::new(T)), }; } |
参见:
- 如何将一个字段移出实现 Drop 特征的结构?