初始化没有克隆的盒装切片或复制

时间:2015-12-15 08:26:11

标签: rust

我正在尝试初始化一组None个值的T,以便基础类型Clone不需要实现Copyfn 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_arrT: 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很新,所以任何提示都会受到赞赏!

1 个答案:

答案 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实际上会检查该长度并仅分配一次。