Rust 使编译器确信数组的每个索引都将被初始化

Rust 使编译器确信数组的每个索引都将被初始化,rust,Rust,我试图为一个由20个元素组成的缓冲区实现Rand特征,这些元素本身实现了Rand特征。我迭代缓冲区并用一个随机值初始化每个元素。但是,我无法说服编译器buff最终将完全初始化 我该怎么做才能让它接受这个 extern crate rand; use rand::{Rand, Rng}; struct Buf20<T>([T; 20]); impl<T: Rand> Rand for Buf20<T> { fn rand<R: Rng>(

我试图为一个由20个元素组成的缓冲区实现
Rand
特征,这些元素本身实现了
Rand
特征。我迭代缓冲区并用一个随机值初始化每个元素。但是,我无法说服编译器
buff
最终将完全初始化

我该怎么做才能让它接受这个

extern crate rand;
use rand::{Rand, Rng};

struct Buf20<T>([T; 20]);

impl<T: Rand> Rand for Buf20<T> {
    fn rand<R: Rng>(rng: &mut R) -> Self {
        let mut buff : [T; 20];
        for element in &mut buff {
            *element = rng.gen();
        }
        Buf20(buff)
    }
}
extern板条箱兰德;
使用rand::{rand,Rng};
结构Buf20([T;20]);
Buf20的impl Rand{
fn rand(rng:&mut R)->自{
让mut buff:[T;20];
用于多个buff中的元素(&M){
*元素=rng.gen();
}
Buf20(浅黄色)
}
}

您无法说服编译器,因为这不一定是真的

这里有两种未知类型,
T
R
,它们的交互作用可能会破坏这里的东西。下面是一些可能的
Rand
Rng
实现,它们将使它爆炸:

struct(Box);
对T的impl Rand{
fn rand(rng:&mut R)->自{
T(Box::new(rng.next_u32())
}
}
结构R(u32);
R的impl Rng{
fn next_u32(&mut self)->u32{
设next=self.0;
自我评价0+=1;
如果self.0>10{
恐慌!();
}
下一个
}
}
基本上,如果
R
有可能触发恐慌,并且
T
有一个析构函数,那么您就进入了未定义的行为,因为数组的元素可能在该阶段都没有初始化
Box
是此类未定义行为的一个特别好的例子,因为您将尝试释放未定义的内存地址

这就是为什么这样使用数组需要(a)有一个长度成员来显示数组中有多少项具有数据,以便您可以跳过其余项的析构函数(当然,这将需要更不安全的代码,并且目前本机不支持简单地禁用析构函数),或者(b)使用
选项
包装每个项目,将未初始化的值设置为
None
,这样非法值的析构函数就不会运行

或者(c)你可以使用向量


目前,固定大小的数组在锈迹斑斑的情况下是二等公民。

如果有一天,我们有一个只写&出的引用,它在写时变为&mut,也许,在没有不安全的情况下编写这种东西会变得更容易?但是迭代器仍然需要说服编译器它将彻底循环。顺便说一句。要使以“渐进式”方式初始化固定大小的数组成为可能,使用另一种“数组生成器”类型就足够了吗?这种类型类似于向量,但分配了堆,固定容量等于固定大小数组的最终大小?在构建器完全初始化之后,它将被转换为一个普通的固定大小数组。这样的机制在将来会很好,并有助于提高数组的地位,但它取决于能否通用地表示数组的长度。这几乎肯定最终会发生,但不会持续很长一段时间。crate实现了这种数组生成器,实际上只适用于选定的数组大小。我担心它不能很好地优化阵列构建,但我们现在没有更好的方法在Rust中实现它。