What is the proper way to initialize a fixed length array?
The safe but somewhat inefficient solution:
#[derive(Copy, Clone, Debug)]struct Foo { a: u32, b: u32,}fn main() { let mut foo_array = [Foo { a: 10, b: 10 }; 10];}
Since you're specifically asking for a solution without copies:
use std::mem::MaybeUninit;#[derive(Debug)]struct Foo { a: u32, b: u32,}// We're just implementing Drop to prove there are no unnecessary copies.impl Drop for Foo { fn drop(&mut self) { println!("Destructor running for a Foo"); }}pub fn main() { let array = { // Create an array of uninitialized values. let mut array: [MaybeUninit<Foo>; 10] = unsafe { MaybeUninit::uninit().assume_init() }; for (i, element) in array.iter_mut().enumerate() { let foo = Foo { a: i as u32, b: 0 }; *element = MaybeUninit::new(foo); } unsafe { std::mem::transmute::<_, [Foo; 10]>(array) } }; for element in array.iter() { println!("{:?}", element); }}
This is recommended by the documentation of MaybeUninit
.
You can use the arrayvec
crate:
Cargo.toml
[package]name = "initialize_array"version = "0.1.0"authors = ["author"]edition = "2018"[dependencies]arrayvec = "0.4.10"
src/main.rs
use arrayvec::ArrayVec; use std::iter;#[derive(Clone)]struct Foo { a: u32, b: u32,}fn main() { let foo_array: [Foo; 10] = iter::repeat(Foo { a: 10, b: 10 }) .collect::<ArrayVec<_>>() .into_inner() .unwrap_or_else(|_| unreachable!());}
The easiest way is to derive Copy
on your type and initialize the array with that, copying the element N
times:
#[derive(Copy)]struct Foo { a: u32, b: u32,}let mut foo_array = [Foo { a: 1, b: 2 }; 10];
If you want to avoid copying, there are a couple options. You can use the Default
trait:
let mut foo_array: [Foo; 10] = Default::default();
However, this is limited to arrays up to 32 elements. With const generics, it is now possible for the standard library to provide Default
for all arrays. However, this would be a backward incompatible change for subtle reasons that are being worked on.
For now, you can take advantage of the fact that const
values are also allowed in array repetition expressions:
const FOO: Foo = Foo { a: 1, b: 2 };let mut foo_array = [FOO; 10];
If you're on nightly, you can use array::map
:
#![feature(array_map)]let mut foo_array = [(); 10].map(|_| Foo::default())