我正在尝试初始化一个装箱的None值片段,以便基础类型T不需要实现Cloneor 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])
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,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()
}
Run Code Online (Sandbox Code Playgroud)
by_vec2没有通过编译器(我不确定我理解为什么),但是by_iter可以。我担心的性能collect- 它是否需要在迭代时调整它所收集的向量的大小,或者它是否可以首先分配正确大小的向量?
也许我的想法是错误的——我对 Rust 很陌生,所以任何建议将不胜感激!
让我们从 开始by_vec2。您正在引用&muta Vec。您不应该这样做,直接使用Vec并使v绑定可变。
然后,您将迭代Vec容量为 5、长度为 0 的 a 的长度。这意味着您的循环永远不会被执行。你想要的是迭代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()
}
Run Code Online (Sandbox Code Playgroud)
您的by_iter函数实际上只分配一次。创建的 Range 迭代器0..5知道它正好有 5 个元素长。因此collect实际上会检查该长度并仅分配一次。