初始化未初始化数组的切片
Initialize slice of an uninitialized array
我有一个奇怪的情况,我想将数组的某些段初始化为现有数组的副本,并调用一个函数来初始化其他元素。天真地,我想做这样的事情:
fn build_array(input: [char; 8]) -> [char; 25] {
let mut out: [char; 25];
out[6..10].copy_from_slice(input[0..4]);
out[16..20].copy_from_slice(input[4..8]);
for i in 0..25 {
if (6..10).contains(i) || (16..20).contains(i) {
continue;
}
out[i] = some_func();
}
}
显然我可以只初始化数组,但那样效率很低。我惊讶地发现将 copy_from_slice()
调用包装在一个不安全的块中并不能编译。创建多个数组段并将它们连接起来似乎并不能简化基于 .
的事情
有谁知道一种惯用且有效的方法来完成我想在这里做的事情?
编辑:some_func()
这里是一个占位符,input
中没有提供的元素并不都具有相同的值。
首先,不用担心初始化元素的开销。特别是当优化器可能会消除它时。
如果您确实需要,例如对于一个非常大的数组,Rust 的方法是使用 MaybeUninit
:
use std::mem::{self, MaybeUninit};
use std::ptr;
fn build_array(input: [char; 8]) -> [char; 25] {
// SAFETY: `MaybeUninit` is always considered initialized (replace with
// `MaybeUninit::uninit_array()` once stabilized).
let mut out: [MaybeUninit<char>; 25] = unsafe { MaybeUninit::uninit().assume_init() };
// SAFETY: source and destination derived from references, slices are of
// the correct length (replace with `MaybeUninit::write_slice()` once stabilized).
unsafe {
ptr::copy_nonoverlapping(
input[0..4].as_ptr(),
out[6..10].as_mut_ptr().cast::<char>(),
4,
);
ptr::copy_nonoverlapping(
input[4..8].as_ptr(),
out[16..20].as_mut_ptr().cast::<char>(),
4,
);
}
for i in 0..25 {
if (6..10).contains(&i) || (16..20).contains(&i) {
continue;
}
out[i].write(some_func());
}
// SAFETY: `MaybeUninit<T>` has the same layout as `T`, initialized above
// (replace with `MaybeUninit::array_assume_init()` once stabilized).
unsafe { mem::transmute(out) }
}
如您所见,这涉及 non-trivial 不安全代码,所以我强烈建议不要这样做,除非确实有必要并且您很清楚自己在做什么。
我有一个奇怪的情况,我想将数组的某些段初始化为现有数组的副本,并调用一个函数来初始化其他元素。天真地,我想做这样的事情:
fn build_array(input: [char; 8]) -> [char; 25] {
let mut out: [char; 25];
out[6..10].copy_from_slice(input[0..4]);
out[16..20].copy_from_slice(input[4..8]);
for i in 0..25 {
if (6..10).contains(i) || (16..20).contains(i) {
continue;
}
out[i] = some_func();
}
}
显然我可以只初始化数组,但那样效率很低。我惊讶地发现将 copy_from_slice()
调用包装在一个不安全的块中并不能编译。创建多个数组段并将它们连接起来似乎并不能简化基于
有谁知道一种惯用且有效的方法来完成我想在这里做的事情?
编辑:some_func()
这里是一个占位符,input
中没有提供的元素并不都具有相同的值。
首先,不用担心初始化元素的开销。特别是当优化器可能会消除它时。
如果您确实需要,例如对于一个非常大的数组,Rust 的方法是使用 MaybeUninit
:
use std::mem::{self, MaybeUninit};
use std::ptr;
fn build_array(input: [char; 8]) -> [char; 25] {
// SAFETY: `MaybeUninit` is always considered initialized (replace with
// `MaybeUninit::uninit_array()` once stabilized).
let mut out: [MaybeUninit<char>; 25] = unsafe { MaybeUninit::uninit().assume_init() };
// SAFETY: source and destination derived from references, slices are of
// the correct length (replace with `MaybeUninit::write_slice()` once stabilized).
unsafe {
ptr::copy_nonoverlapping(
input[0..4].as_ptr(),
out[6..10].as_mut_ptr().cast::<char>(),
4,
);
ptr::copy_nonoverlapping(
input[4..8].as_ptr(),
out[16..20].as_mut_ptr().cast::<char>(),
4,
);
}
for i in 0..25 {
if (6..10).contains(&i) || (16..20).contains(&i) {
continue;
}
out[i].write(some_func());
}
// SAFETY: `MaybeUninit<T>` has the same layout as `T`, initialized above
// (replace with `MaybeUninit::array_assume_init()` once stabilized).
unsafe { mem::transmute(out) }
}
如您所见,这涉及 non-trivial 不安全代码,所以我强烈建议不要这样做,除非确实有必要并且您很清楚自己在做什么。