【问题标题】:Convert Vec<Box<Foo>> to &[&Foo] in Rust在 Rust 中将 Vec<Box<Foo>> 转换为 &[&Foo]
【发布时间】:2020-01-09 22:00:41
【问题描述】:

我正在通过借用Vec&lt;Box&lt;Foo&gt;&gt; 字段来在结构上实现一个方法,该方法应返回&amp;[&amp;Foo]。我将如何实现它?

我尝试通过将Vec&lt;Box&lt;Foo&gt;&gt; 映射到Vec&lt;&amp;Foo&gt; 来进行转换,但是这随后被分配到堆栈上,这意味着它的一部分无法返回。

这是一个问题的例子:

struct Bar {
    baz: Vec<Box<Foo>>,
}

impl Bar {
    pub fn buzz(&self) -> &[&Foo] {
        // How do I implement this to return
        // the data that is in self.baz?
    }
}

【问题讨论】:

  • Vec&lt;Box&lt;T&gt;&gt; should only be used in very specific situations,例如当T 未调整大小时。否则,您可以考虑不使用额外的参考层。您也可以考虑不转换这些框并简单地返回&amp;[Box&lt;Foo&gt;],在这种情况下更容易获得。
  • 如果没有分配,您将无法执行此操作 - 您要么需要一个中间映射步骤才能将 Box&lt;Foo&gt; 转换为 &amp;Foo(即使这样也是有风险的,因为您是暗示 Foo:Sized` 这样做是为了获得 Vec&lt;&amp;Foo&gt; 并可以调用 as_slice(),或者您需要保留 &amp;[Box&lt;Foo&gt;] 并从那里分配每个元素。不过,您的目标是什么?
  • @SébastienRenauld 在这种情况下 Foo 是一个特征对象,这意味着我必须将它包装在一个盒子中。我觉得使用 Vec 作为返回类型会多余地返回一个拥有的向量,因为它在概念上只是一些现有数据的不可变视图。
  • @SCappella 不幸的是 Foo 确实没有尺寸,因此是盒子。另外我相信返回 &[Box] 意味着每个元素的所有权都不起作用。
  • 出于审美原因,&amp;[] 中的 &amp; 确实不存在。它不是自有结构。

标签: reference rust type-conversion slice


【解决方案1】:

您可以通过unsafe 强制来做到这一点:

pub fn buzz(&self) -> &[&Foo] {
    unsafe {
        std::slice::from_raw_parts(self.baz.as_ptr() as *const _, self.baz.len())
    }
}

这很好,因为:

  1. 如果Foo 是动态调整大小的,那么Box&lt;Foo&gt; 是一个胖指针。但是&amp;Foo 也是如此,因此它们始终具有相同的布局。
  2. 函数签名强制借用的生命周期不能超过&amp;self的借用,因此借用时不可能丢弃盒子。

正如其他人在 cmets 中所暗示的那样,如果您发现自己需要不安全的代码来处理表面上简单的情况,而 std 无法满足您的需求,那么您可能在自己的代码库中解决了一个糟糕的设计决策。尽可能避免使用unsafe,并在考虑使用应用程序之前仔细检查应用程序的整个设计。

【讨论】:

  • 这行得通,但这似乎不是一个好主意。从概念上讲,我只是在一组拥有的、未调整大小的数据上返回一个不可变的视图。有什么比返回应该使用的 &[&Foo] 更惯用的方法吗?我觉得 Vec 有点重,因为它需要浅拷贝向量来实现概念上的借用。
  • @Llew &amp;[Box&lt;Foo&gt;] 就是这样:拥有数据集合的不可变视图。 &amp;[&amp;Foo] 将是对您没有的数据引用集合的视图。由于您没有Vec&lt;&amp;Foo&gt;,因此您不能在没有不安全代码的情况下借用&amp;[&amp;Foo](尽管正如彼得指出的那样,这里使用unsafe 是合理的)。
  • @LlewVallis &amp;Foo 是对堆栈或堆上任何位置的Foo 的引用,这无关紧要。 Box&lt;Foo&gt; 特别是对堆上的 Foo 的引用。所以&amp;[&amp;Foo]&amp;[Box&lt;Foo&gt;] 都是指针切片(在这种情况下是胖指针)。那么第一种形式比第二种形式有什么优势呢?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多