所以,有一些结构看起来像这样:
struct foo {
alpha: Vec<T>,
beta: Vec<T>,
}
并且某些方法应该移动一些与alpha
到beta
的某些条件匹配的值。问题是:如果不拥有self
,干净的方式是什么?
无法使用Vec::partition()
方法,因为self.alpha
的任何移动都会导致cannot move out of dereference of &mut-pointer
编译错误。
PS:T
里面有File
,所以它没有实现Clone
。
答案 0 :(得分:3)
你想放弃beta
吗?这是std::mem::replace
的用途,允许你把它拉出来:
use std::mem;
impl Foo {
fn munge(&mut self) {
let alpha = mem::replace(&mut self.alpha, Vec::new());
let (alpha, beta) = alpha.partition(…);
self.alpha = alpha;
self.beta = beta;
}
}
请注意, 是在那里短暂创建的新Vec
,但这并不重要;它不涉及分配,而且非常便宜。 (另一种方法是在那里留下未初始化的内存并再次替换它,忘记未初始化的内存,但如果分区失败则不安全,因为它将在未初始化的内存上运行析构函数。)
由于您只想移动与谓词匹配的元素,因此值得研究partition
的实现方式:
pub fn partition<F>(self, mut f: F) -> (Vec<T>, Vec<T>) where F: FnMut(&T) -> bool {
let mut lefts = Vec::new();
let mut rights = Vec::new();
for elt in self.into_iter() {
if f(&elt) {
lefts.push(elt);
} else {
rights.push(elt);
}
}
(lefts, rights)
}
知道这是它的实现方式使得实现类似于不涉及创建第二个向量的东西是相当容易的;这是一般的想法:
let source = mem::replace(&mut self.alpha, Vec::new());
for element in source.into_iter() {
if f(&element) { /* for some `f` */
self.alpha.push(element)
} else {
self.beta.push(element)
}
}
真的,mem::replace
是你需要知道的关于这些事情的唯一事情;其余的变得相当容易。