我主张按值 merge 应该不成为您的基本实现。相反,变异方法提供了更大的灵活性。然后,您可以在此基础上构建按值和按框值方法:
struct A(u8);
impl A {
fn merge_ref(&mut self, other: &A) {
self.0 += other.0
}
}
fn merge(mut a1: A, a2: A) -> A {
a1.merge_ref(&a2);
a1
}
fn boxed_merge(mut a1: Box<A>, a2: Box<A>) -> Box<A> {
a1.merge_ref(&a2);
a1
}
fn main() {
let a1 = A(1);
let a2 = A(2);
let a3 = merge(a1, a2);
let boxed_a3 = Box::new(a3);
let boxed_a4 = Box::new(A(4));
let boxed_a7 = boxed_merge(boxed_a3, boxed_a4);
println!("{}", boxed_a7.0);
}
值得注意的是,这在盒装情况下会更有效,因为您不必执行任何额外的分配。
As oli_obk - ker points out:
这仅适用于 Copy 结构的合并。如果您有两个合并的集合,则集合的元素可能不可复制
这可以通过在merge_ref 中按值合并并使用相同的技巧在boxed_merge 方法中移出框来解决:
struct B(Vec<u8>);
impl B {
fn merge_ref(&mut self, other: B) {
self.0.extend(other.0)
}
}
fn merge(mut b1: B, b2: B) -> B {
b1.merge_ref(b2);
b1
}
fn boxed_merge(mut b1: Box<B>, b2: Box<B>) -> Box<B> {
b1.merge_ref(*b2);
b1
}
fn main() {
let b1 = B(vec![1]);
let b2 = B(vec![2]);
let b3 = merge(b1, b2);
let boxed_b3 = Box::new(b3);
let boxed_b4 = Box::new(B(vec![4]));
let boxed_b7 = boxed_merge(boxed_b3, boxed_b4);
println!("{:?}", boxed_b7.0);
}
我们这里仍然没有任何额外的分配。