如何复制共享切片以具有盒装切片?

时间:2019-05-30 06:40:02

标签: rust

我有一个容器:

pub struct Foo<T> {
    pub data: Box<[T]>,
}

我想要一种从现有切片中初始化一个新切片的方法:

impl<T> Foo<T> {
    fn from_slice(slice: &[T]) -> Foo<T> {
        Foo {
            data: Box::new(/* something here */),
        }
    }
}

我想从任何种类的切片中创建一个Foo实例,这些实例来自动态矢量或静态字符串。

我认为vec!是宏是有原因的,但是有什么方法可以避免写一个宏?我想我可以slice.to_vec().into_boxed_slice()做,但是创建Vec作为克隆的代理似乎不正确……

我没有在结构中使用Vec,因为data在容器的生存期内不应该改变大小。使用Vec并不正确,但我可能是错的。

1 个答案:

答案 0 :(得分:4)

如果切片包含Copy类型,则可以使用From / Into进行构造:

pub struct Foo<T> {
    pub data: Box<[T]>,
}

impl<T> Foo<T> {
    fn from_slice(slice: &[T]) -> Foo<T>
    where
        T: Copy,
    {
        Foo { data: slice.into() }
    }
}

如果您的数据是Clone,则可以使用to_vec + into_boxed_slice

impl<T> Foo<T> {
    fn from_slice(slice: &[T]) -> Foo<T>
    where
        T: Clone,
    {
        Foo { data: slice.to_vec().into_boxed_slice() }
    }
}
  

创建Vec作为克隆的代理似乎不正确

没有在这里克隆。克隆类型T时,将返回类型T。您从&[T]开始,想获得一个Box<[T]>,而不是[T](您无法拥有)。

通过Vec创建装箱的切片意味着您暂时占用了3个机器大小的整数,而不是2;与执行的分配数量相比,这不太可能是性能问题。

我确实同意starblue's answer的观点,在大多数情况下,保留Vec<T>可能会更简单,但是我承认,有时会有盒装切片很有用。

另请参阅:

  

我认为vec!是宏

是有原因的

implementation of vec!是公开的:

macro_rules! vec {
    ($elem:expr; $n:expr) => (
        $crate::vec::from_elem($elem, $n)
    );
    ($($x:expr),*) => (
        <[_]>::into_vec(box [$($x),*])
    );
    ($($x:expr,)*) => (vec![$($x),*])
}

为方便语法,它实际上只是一个宏(并且因为它使用了不稳定的box关键字);它接受参数,创建一个数组,将其装箱,将其强制为装箱的切片,然后将其转换为Vec