初始化未初始化数组的切片

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 不安全代码,所以我强烈建议不要这样做,除非确实有必要并且您很清楚自己在做什么。