如何惯用地复制切片?

How to idiomatically copy a slice?

在 Go 中,复制切片是标准的,看起来像这样:

# It will figure out the details to match slice sizes
dst = copy(dst[n:], src[:m])

在 Rust 中,我找不到类似的方法作为替换。我想出的东西看起来像这样:

fn copy_slice(dst: &mut [u8], src: &[u8]) -> usize {
    let mut c = 0;
    for (&mut d, &s) in dst.iter_mut().zip(src.iter()) {
        d = s;
        c += 1;
    }
    c
}

不幸的是,我遇到了无法解决的编译错误:

error[E0384]: re-assignment of immutable variable `d`
 --> src/main.rs:4:9
  |
3 |     for (&mut d, &s) in dst.iter_mut().zip(src.iter()) {
  |               - first assignment to `d`
4 |         d = s;
  |         ^^^^^ re-assignment of immutable variable

如何设置d?有没有更好的复制切片的方法?

这段代码有效,尽管我不确定它是否是最好的方法。

fn copy_slice(dst: &mut [u8], src: &[u8]) -> usize {
    let mut c = 0;
    for (d, s) in dst.iter_mut().zip(src.iter()) {
        *d = *s;
        c += 1;
    }
    c 
}

显然没有明确指定访问权限就成功了。然而,我仍然对此感到困惑,我的心智模型还没有涵盖那里真正发生的事情。 当涉及到这些事情时,我的解决方案主要是反复试验,我宁愿真正理解。

是的,使用方法 clone_from_slice(),它对实现 Clone.

的任何元素类型都是通用的
fn main() {
    let mut x = vec![0; 8];
    let y = [1, 2, 3];
    x[..3].clone_from_slice(&y);
    println!("{:?}", x);
    // Output:
    // [1, 2, 3, 0, 0, 0, 0, 0]
}

目标 x 是一个 &mut [T] 切片,或者是任何对其取消引用的东西,例如可变 Vec<T> 向量。您需要对目标和源进行切片,以便它们的长度匹配。


从 Rust 1.9 开始,您还可以使用 copy_from_slice()。它以相同的方式工作,但使用 Copy 特性而不是 Clone,并且是 memcpy 的直接包装器。编译器可以在适用时优化 clone_from_slice 等同于 copy_from_slice,但它仍然有用。

另一种变体是

fn copy_slice(dst: &mut [u8], src: &[u8]) -> usize {
    dst.iter_mut().zip(src).map(|(x, y)| *x = *y).count()
}

请注意,在这种情况下您必须使用 count,因为 len 会使用 ExactSizeIterator 快捷方式,因此永远不会调用 next,从而导致 no-操作