在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
?有没有更好的方法来复制切片?
答案 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)
警告 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
,从而导致无操作。