Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the proper way to initialize a fixed length array?

Tags:

arrays

rust

I'm having trouble initializing a fixed length array. My attempts so far all result in the same "use of possibly uninitialized variable: foo_array" error:

#[derive(Debug)] struct Foo { a: u32, b: u32 }  impl Default for Foo {     fn default() -> Foo { Foo{a:1, b:2} } }  pub fn main() {     let mut foo_array: [Foo; 10];      // Do something here to in-place initialize foo_array?      for f in foo_array.iter() {         println!("{:?}", f);     } } 
error[E0381]: use of possibly uninitialized variable: `foo_array`   --> src/main.rs:13:14    | 13 |     for f in foo_array.iter() {    |              ^^^^^^^^^ use of possibly uninitialized `foo_array` 

I implemented the Default trait, but Rust does not seem to call this by default akin to a C++ constructor.

What is the proper way to initialize a fixed length array? I'd like to do an efficient in-place initialization rather than some sort of copy.

Related: Why is the Copy trait needed for default (struct valued) array initialization?

Related: Is there a way to not have to initialize arrays twice?

like image 988
srking Avatar asked Jul 11 '15 19:07

srking


People also ask

How do you initialize an array length?

The slow way to initialize your array with non-default values is to assign values one by one: int[] intArray = new int[10]; intArray[0] = 22; In this case, you declared an integer array object containing 10 elements, so you can initialize each element using its index value.

How do you create an array of fixed lengths?

Use a tuple to declare an array with fixed length in TypeScript, e.g. const arr: [string, number] = ['a', 1] . Tuple types allow us to express an array with a fixed number of elements whose types are known, but can be different. Copied! We declared a tuple with 3 elements with types of string , number and number .

Which is the correct way to initialize the array variable?

You initialize an array variable by including an array literal in a New clause and specifying the initial values of the array. You can either specify the type or allow it to be inferred from the values in the array literal.


1 Answers

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.

like image 104
A.B. Avatar answered Oct 06 '22 01:10

A.B.