【发布时间】:2014-08-10 03:45:54
【问题描述】:
如果我有两个不同大小的数组:
let mut array1 = [0; 8];
let array2 = [1, 2, 3, 4];
如何将array2 复制到array1 的前4 个字节中?我可以获取 array1 的可变 4 字节切片,但我不确定如何或是否可以分配给它。
【问题讨论】:
如果我有两个不同大小的数组:
let mut array1 = [0; 8];
let array2 = [1, 2, 3, 4];
如何将array2 复制到array1 的前4 个字节中?我可以获取 array1 的可变 4 字节切片,但我不确定如何或是否可以分配给它。
【问题讨论】:
手动即可
for (dst, src) in array1.iter_mut().zip(&array2) {
*dst = *src
}
对于一个典型的切片。但是,clone_from_slice 的专业化可能更快:
dst[..4].clone_from_slice(&src)
一种稍旧的方法是使用std::io::Write,它是为&mut [u8] 实现的。
use std::io::Write;
let _ = dst.write(&src)
这将写入直到dst 的末尾,并返回在Result 中写入了多少值。如果您使用write_all,如果不是所有字节都可以写入,这将返回Err。
【讨论】:
最灵活的方式是使用迭代器依次处理每个元素:
for (place, data) in array1.iter_mut().zip(array2.iter()) {
*place = *data
}
.mut_iter 创建an Iterator that yields &mut u8,即指向切片/数组的可变引用。 iter 做同样的事情,但使用 shared references。 .zip 采用两个迭代器并以锁步方式遍历它们,将两者中的元素作为一个元组产生(并在其中一个停止时立即停止)。
如果您需要/想要在写信给place 之前对数据做任何“花哨”的事情,这就是使用的方法。
但是,普通复制功能也作为单一方法提供,
.copy_from,类似array1.copy_from(array2)。
std::slice::bytes::copy_memory,尽管您需要修剪这两个数组,因为copy_memory 要求它们的长度相同:
use std::cmp;
use std::slice::bytes;
let len = cmp::min(array1.len(), array2.len());
bytes::copy_memory(array1.mut_slice_to(len), array2.slice_to(len));
(如果您知道array1 总是比array2 长,那么bytes::copy_memory(array1.mut_slice_to(array2.len()), array2) 也应该可以工作。)
目前,bytes 版本的优化效果最好,最低为 memcpy 调用,但希望 rustc/LLVM 的改进最终能实现这一目标。
【讨论】:
mut_iter 至少从 1.0.0 (可能更早?)起已重命名为 iter_mut
您可以简单地使用copy_from_slice() 并使用Range & Co:
fn main() {
let mut dest = [0; 8];
let src = [1, 2, 3, 4];
dest[..4].copy_from_slice(&src);
assert_eq!(dest, [1, 2, 3, 4, 0, 0, 0, 0]);
}
反例:
fn main() {
let src = [1, 2, 3, 4, 5, 6, 7, 8];
let mut dest = [0; 4];
dest.copy_from_slice(&src[2..6]);
assert_eq!(dest, [3, 4 ,5, 6]);
}
组合案例:
fn main() {
let src = [1, 2, 3, 4, 5, 6, 7, 8];
let mut dest = [0; 4];
dest[1..3].copy_from_slice(&src[3..5]);
assert_eq!(dest, [0, 4, 5, 0]);
}
【讨论】: