Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 如何创建和初始化不可变数组?_Arrays_Immutability_Rust - Fatal编程技术网

Arrays 如何创建和初始化不可变数组?

Arrays 如何创建和初始化不可变数组?,arrays,immutability,rust,Arrays,Immutability,Rust,我想创建一个数组。我不需要数组是可变的,在创建时,我拥有计算数组第I个成员所需的所有信息。但是,我不知道如何在Rust中创建不可变数组 以下是我现在拥有的: let mut my_array: [f32; 4] = [0.0; 4]; for i in 0..4 { // some calculation, doesn't matter what exactly my_array[i] = some_function(i); } 这就是我想要的: let my_array: [

我想创建一个数组。我不需要数组是可变的,在创建时,我拥有计算数组第I个成员所需的所有信息。但是,我不知道如何在Rust中创建不可变数组

以下是我现在拥有的:

let mut my_array: [f32; 4] = [0.0; 4];
for i in 0..4 {
    // some calculation, doesn't matter what exactly
    my_array[i] = some_function(i);
}
这就是我想要的:

let my_array: [f32; 4] = array_factory!(4, some_function);

如何在Rust中实现这一点?

尝试将宏扩展到以下内容:

let my_array = {
    let mut tmp: [f32, ..4u] = [0.0, ..4u];
    for i in range(0u, 4u) {
        tmp[i] = somefunction(i);
    }
    tmp
};

我不知道的是,这是否经过了适当的优化,以避免将
tmp
移动到
myu数组
。但对于4个f32值(128位),这可能不会产生显著差异。

以下是宏定义和示例用法:

macro_rules! array_factory(
    ($size: expr, $factory: expr) => ({
        unsafe fn get_item_ptr<T>(slice: *mut [T], index: usize) -> *mut T {
            (slice as *mut T).offset(index as isize)
        }

        let mut arr = ::std::mem::MaybeUninit::<[_; $size]>::uninit();
        unsafe {
            for i in 0..$size {
                ::std::ptr::write(get_item_ptr(arr.as_mut_ptr(), i), $factory(i));
            }
            arr.assume_init()
        }
    });
);

fn some_function(i: usize) -> f32 {
    i as f32 * 3.125
}

fn main() {
    let my_array: [f32; 4] = array_factory!(4, some_function);
    println!("{} {} {} {}", my_array[0], my_array[1], my_array[2], my_array[3]);
}


有一个很好的理由。此答案的早期版本使用了
mem::uninitialized
,它不是内存安全的:如果在初始化数组时发生死机(因为工厂函数死机),并且数组的项类型有一个析构函数,编译器将插入代码来调用数组中每个项的析构函数;即使是尚未初始化的项目
maybeunit
避免了这个问题,因为它将初始化的值封装在Rust中,这是Rust中的一种魔法类型,可以防止析构函数自动运行。

+1很好!但我几乎可以肯定你的作业是错的。您需要改用
::std::ptr::write
。否则对未初始化的值调用
drop
。我想知道
[std::uninitialized(),…N]
是一个no op还是涉及N个函数调用。我认为对整个数组使用单个
std::uninitialized()
是一种更好的方法。在本例中,它似乎用两次移动来初始化整个阵列。使用-O0,它正在调用
未初始化()
,但不是在循环中。谢谢!但是来自C#,我有一个习惯,就是尽量避免
不安全的
块。(顺便说一句,这仍然是一个好习惯,还是我应该放弃它?)我是否正确地理解,您使用不安全块的唯一原因是不依赖于正在实现的
Default::Default()
?@golergka:避免
unsafe
仍然是一个好习惯。在本例中,它用于避免必须使用一些伪元素初始化数组的问题。
macro_rules! array_factory(
    ($size: expr, $factory: expr) => ({
        let mut arr = [::std::default::Default::default(), ..$size];
        for i in 0..$size {
            arr[i] = $factory(i);
        }
        arr
    });
)