如何习惯性地复制切片?

时间:2015-01-29 16:05:19

标签: rust 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?有没有更好的方法来复制切片?

4 个答案:

答案 0 :(得分:27)

是的,使用方法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,但它仍然有用。

答案 1 :(得分:3)

自Rust 1.6.0以来,

警告 copy_memory已被弃用。查看bluss' answer以获得稳定的解决方案。


我可能会使用copy_memory,其几乎与您想要的签名相同

use std::slice::bytes;
use std::cmp;

fn copy_slice(dst: &mut [u8], src: &[u8]) -> usize {
    let len = cmp::min(src.len(), dst.len());
    bytes::copy_memory(&mut dst[..len], &src[..len]);
    len
}

fn main() {
    let mut a = [1u8, 2, 3];
    let mut b = [9u8];

    //copy_slice(&mut a[], &b[]);
    copy_slice(&mut b[], &a[]);

    println!("{:?}, {:?}", a, b);
}

请注意,这是不是通用解决方案。在Rust中,切片可以是任何类型,包括那些不易复制的切片!你的问题和这个答案只涉及u8

的切片

答案 2 :(得分:2)

此代码有效,即使我不确定它是否是最好的方法。

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 
}

显然没有明确指定访问权限。但是,我仍然对此感到困惑,我的心理模型还没有涵盖那里真正发生的事情。 对于这些事情,我的解决方案大多是反复试验,我宁愿真正理解。

答案 3 :(得分:-1)

另一种变体是

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

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