初始化固定长度数组的正确方法是什么?

时间:2015-07-11 19:31:48

标签: arrays rust

我在初始化固定长度数组时遇到问题。 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`

我实现了Default特征,但是Rust似乎并没有默认调用它类似于C ++构造函数。

初始化固定长度数组的正确方法是什么?我想做一个有效的就地初始化而不是某种副本。

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

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

3 个答案:

答案 0 :(得分:20)

安全但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];
}

因为您特别要求a solution without copies

use std::{mem, ptr};

#[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 = unsafe {
        // Create an uninitialized array.
        let mut array: [Foo; 10] = mem::uninitialized();

        for (i, element) in array.iter_mut().enumerate() {
            let foo = Foo { a: i as u32, b: 0 };

            // Overwrite `element` without running the destructor of the old value.
            // Since Foo does not implement Copy, it is moved.
            ptr::write(element, foo)
        }

        array
    };

    for element in array.iter() {
        println!("{:?}", element);
    }
}

答案 1 :(得分:5)

您可以使用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!());
}

答案 2 :(得分:0)

最简单的方法是在您的类型上派生 Copy 并用它初始化数组,复制元素 N 次:

#[derive(Copy)]
struct Foo {
    a: u32,
    b: u32,
}

let mut foo_array = [Foo { a: 1, b: 2 }; 10];

如果您想避免复制,有几个选项。您可以使用 Default 特性:

let mut foo_array: [Foo; 10] = Default::default();

但是,这仅限于最多 32 个元素的数组。使用 const 泛型,标准库现在可以为 all 数组提供 Default。但是,由于正在处理的微妙原因,这将是向后不兼容的更改。

现在,您可以利用数组重复表达式中也允许使用 const 值这一事实:

const FOO: Foo = Foo { a: 1, b: 2 };

let mut foo_array = [FOO; 10];

如果您每晚都在,您可以使用 array::map

#![feature(array_map)]

let mut foo_array = [(); 10].map(|_| Foo::default())