5 个版本

0.1.4 2021 年 5 月 28 日
0.1.3 2021 年 5 月 28 日
0.1.2 2021 年 5 月 27 日
0.1.1 2021 年 5 月 27 日
0.1.0 2021 年 5 月 27 日

44#impl 中排名

Download history 7/week @ 2024-02-05 14/week @ 2024-02-19 13/week @ 2024-02-26 6/week @ 2024-03-04 24/week @ 2024-03-11 7/week @ 2024-03-18 20/week @ 2024-03-25 25/week @ 2024-04-01 6/week @ 2024-04-08 22/week @ 2024-04-15

每月下载 74
用于 array_iter_tools

MIT 许可证

12KB
146 代码行

array_builder

ArrayBuilder 对 Rust 的实现。 https://github.com/rust-lang/rfcs/pull/3131


lib.rs:

当前动态数组初始化非常危险。最安全的方法是使用默认值初始化一个数组

let mut array = [0; 32];
for i in 0..32 {
    array[i] = i;
}

但这通常是不可能的。对于任何类型 [T; N],T 既要能够 Copy,或者需要有一个 const t: T。这绝对不是总是情况。

第二个问题是效率。在上面的例子中,我们用零填充了一个数组,只是为了替换它们。虽然编译器有时可以优化这部分,但有一个保证会更好。

那么,替代方案是什么?使用 MaybeUninit 如何!尽管,这并不简单。以下是一个使用完全安全的 Rust 的例子,你能找出错误吗?

let mut uninit: [MaybeUninit<String>; 8] = MaybeUninit::uninit_array();
uninit[0].write("foo".to_string());
uninit[1].write("bar".to_string());
uninit[2].write("baz".to_string());
panic!("oops");

你发现了错误吗?就在那里有一个内存泄漏。关键在于 MaybeUninit 不实现 Drop。这很有道理,因为值可能未被初始化,对未初始化值调用 Drop 是未定义的行为。结果是,我们初始化的 3 个 String 值从未被丢弃!虽然这根据 Rust 是安全的。内存泄漏不是未定义的行为。但这仍然不是我们应该提倡的事情。

我们还有哪些其他选择?唯一的解决方案是提供一个新的struct来封装数组,并正确实现Drop。这样,如果调用drop,我们可以确保任何初始化的值都能被正确释放。这正是ArrayBuilder提供的内容。

use array_builder::ArrayBuilder;
let mut uninit: ArrayBuilder<String, 8> = ArrayBuilder::new();
uninit.push("foo".to_string());
uninit.push("bar".to_string());
uninit.push("baz".to_string());
panic!("oops"); // ArrayBuilder drops the 3 values above for you
use array_builder::ArrayBuilder;
let mut uninit: ArrayBuilder<String, 3> = ArrayBuilder::new();
uninit.push("foo".to_string());
uninit.push("bar".to_string());
uninit.push("baz".to_string());
let array: [String; 3] = uninit.build().unwrap();

您还可以查看当前已初始化的值集合

use array_builder::ArrayBuilder;
let mut uninit: ArrayBuilder<usize, 4> = ArrayBuilder::new();
uninit.push(1);
uninit.push(2);
uninit.push(3);

// we can't build just yet
let mut uninit = uninit.build().unwrap_err();
let slice: &[usize] = &uninit;
assert_eq!(&[1, 2, 3], slice);

uninit.push(4);
assert_eq!([1, 2, 3, 4], uninit.build().unwrap());

无运行时依赖