我有一个容器:
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
并不正确,但我可能是错的。
答案 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!
是宏
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
。