【问题标题】:Merge boxed elements合并盒装元素
【发布时间】:2017-05-17 07:33:49
【问题描述】:

假设存在以下函数:

fn merge(a1: A, a2: A) -> A { /* implemented */ }

有没有办法使用盒装类型为相同的操作编写函数?那就是:

fn boxed_merge(a1: Box<A>, a2: Box<A>) -> Box<A> { /* ??? */ }

【问题讨论】:

  • 您如何看待a1a2 之间的合并?
  • 我认为合并为:merge(a1: A, a2: A) -&gt; A。编辑了我的问题以使其更清楚。

标签: rust


【解决方案1】:

我主张按值 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);
}

我们这里仍然没有任何额外的分配。

【讨论】:

  • 这仅适用于复制结构的合并。如果您有两个合并的集合,则集合的元素可能不可复制(例如Box&lt;T&gt;)。
  • @oli_obk-ker 确实如此,但如果是这种情况,我会更改为 fn merge_ref(&amp;mut self, other: A),它具有避免无关分配的相同好处。
【解决方案2】:

您可以通过取消引用 boxed_merge 函数内的框来重复使用您的 merge 函数。请注意,这不会重新使用分配,而是创建一个新的

fn boxed_merge(a1: Box<A>, a2: Box<A>) -> Box<A> {
    Box::new(merge(*a1, *a2))
}

【讨论】:

  • 重用非盒子函数的好主意。
【解决方案3】:

您可以通过取消引用来访问装箱参数的内容,并将它们组合到一个新的Box 中。例如:

fn merge(a1: Box<usize>, a2: Box<usize>) -> Box<usize> {
    Box::new(*a1 + *a2)
}

fn main() {
    let a1 = Box::new(1);
    let a2 = Box::new(2);

    println!("{}", merge(a1, a2));
}

【讨论】:

    猜你喜欢
    • 2012-08-01
    • 2017-10-22
    • 1970-01-01
    • 2015-05-04
    • 2020-09-09
    • 1970-01-01
    • 2021-06-15
    • 1970-01-01
    • 2012-04-28
    相关资源
    最近更新 更多