我正在尝试初始化一组None
个值的T
,以便基础类型Clone
不需要实现Copy
或fn by_vec<T>() -> Box<[Option<T>]> {
vec![None; 5].into_boxed_slice()
}
fn by_arr<T>() -> Box<[Option<T>]> {
Box::new([None; 5])
}
。这里有一些理想的解决方案:
by_vec
不幸的是,T: Clone
实施需要by_arr
,T: Copy
实施需要fn by_vec2<T>() -> Box<[Option<T>]> {
let v = &mut Vec::with_capacity(5);
for i in 0..v.len() {
v[i] = None;
}
v.into_boxed_slice() // Doesn't work: cannot move out of borrowed content
}
fn by_iter<T>() -> Box<[Option<T>]> {
(0..5).map(|_| None).collect::<Vec<Option<T>>>().into_boxed_slice()
}
。我已经尝试了一些方法:
by_vec2
by_iter
没有通过编译器(我不确定我理解为什么),但collect
确实如此。我关注width: auto;
的性能 - 它需要调整它在迭代时收集的向量,还是可以分配正确大小的向量?
也许我说这一切都错了 - 我对Rust很新,所以任何提示都会受到赞赏!
答案 0 :(得分:4)
让我们从by_vec2
开始吧。您正在&mut
引用Vec
。您不应该这样做,直接使用Vec
并使v
绑定变为可变。
然后,您将迭代Vec
的长度,容量为5,长度为0.这意味着您的循环永远不会被执行。你想要的是迭代0..v.cap()
。
由于v
的长度仍为0,因此在循环中访问v[i]
会在运行时出现混乱。你真正想要的是v.push(None)
。这通常会导致重新分配,但在您的情况下,您已经分配了Vec::with_capacity
,因此推送5次将不会分配。
这一次,我们没有引用Vec
,因此into_boxed_slice
实际上会有效。
fn by_vec2<T>() -> Box<[Option<T>]> {
let mut v = Vec::with_capacity(5);
for _ in 0..v.capacity() {
v.push(None);
}
v.into_boxed_slice()
}
您的by_iter
函数实际上只分配一次。由0..5
创建的Range迭代器知道正好是5个元素长。因此collect
实际上会检查该长度并仅分配一次。