固定数组初始化而不实现 Copy 或 Default 特性

Fixed array initialization without implementing Copy or Default trait

我想制作一个二维固定大小的数组,它将在 for 循环中初始化。这是示例代码(由于某些原因,Cell 结构无法实现 Copy 或 Default 特性):

let mut cells: [[Cell; 20]; 20];
for i in 0..20 {
    for j in 0..20 {
        cells[i][j] = Cell::new(some_value_based_on_i_and_j);
    }
}

but then compiler gives this error:

使用可能未初始化的变量

所以为了向编译器保证我的数组至少被完全初始化了1次;我把它改成这样:

let mut cells: [[Cell; 20]; 20] = [[Cell::new(default_value); 20]; 20];
for i in 0..20 {
    for j in 0..20 {
        cells[i][j] = Cell::new(some_value_based_on_i_and_j);
    }
}

(事实上,我想听编译器并使用类似这种模式的默认值初始化数组的所有索引,然后执行我之前的工作):

 let a = [-12, 100] // means -> [default_value, repetition_or_also_length_of_the_array]

Then the compiler gives this error:

特征界限[maze_maker::Cell; 20]: std::marker::Copy不满足

特征 std::marker::Copy 没有为 [maze_maker::Cell; 20]

实现

注意:Copy trait 是必需的,因为重复的元素将被复制

我该怎么做):?

array_init crate 在这里可能对您有所帮助,它可以让您创建一个数组,方法是给它一个将重复调用的函数,或者收集一个迭代器。

如果你不介意临时分配,你可以利用 Vec<T> 实现 TryInto<[T; N]> 的事实,如果 运行 的长度返回错误 Vec 不适合数组的大小。它不是特别优雅,但不需要不安全:

let cells: [[Cell<usize>; 20]; 20] = (0..20)
    .map(|i| {
        (0..20)
            .map(|j| Cell::new(i + j))
            .collect::<Vec<_>>()
            .try_into()
            .unwrap()
    })
    .collect::<Vec<_>>()
    .try_into()
    .unwrap();

如果您可以使用外部板条箱,您可以调整以上内容以使用 arrayvec 来避免分配:

let cells: [[Cell<usize>; 20]; 20] = (0..20)
    .map(|i| {
        (0..20)
            .map(|j| Cell::new(i + j))
            .collect::<ArrayVec<_, 20>>()
            .into_inner()
            .unwrap()
    })
    .collect::<ArrayVec<_, 20>>()
    .into_inner()
    .unwrap();

另一方面,如果您已经在使用外部包装箱,那么其他答案推荐的 array_init 包装箱可能更合适。