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

问题描述 投票:0回答:1

我有一个奇怪的情况,我想将数组的某些段初始化为现有数组的副本,并调用函数来初始化其他元素。天真地,我想做这样的事情:

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
中未提供的元素并不都具有相同的值。

arrays rust initialization slice
1个回答
3
投票

首先,不要担心初始化元素的成本。特别是当优化器可能消除它时。

如果您确实需要,例如对于非常大的数组,Rust 方法是使用

MaybeUninit
:

use std::mem::{self, MaybeUninit};
use std::ptr;

fn build_array(input: [char; 8]) -> [char; 25] {
    // `MaybeUninit::uninit_array()` once stabilized).
    let mut out: [MaybeUninit<char>; 25] = [MaybeUninit::uninit(); 25];
    // 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) }
}

正如您所看到的,这涉及到不平凡的不安全代码,因此我强烈建议不要这样做,除非确实有必要并且您很清楚自己在做什么。

© www.soinside.com 2019 - 2024. All rights reserved.