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

Gol*_*nks 2 rust

我正在尝试为Rand20个元素的缓冲区实现特性,这些元素实现了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)
    }
}
Run Code Online (Sandbox Code Playgroud)

Chr*_*gan 5

您将无法使编译器相信这一点,因为它不一定是真的.

有两种类型不明这里,TR和它们之间的相互作用可以在这里打破东西.这里有一对夫妇的可能实现的Rand,并Rng把将炸毁:

struct T(Box<u32>);

impl Rand for T {
    fn rand<R: Rng>(rng: &mut R) -> Self {
        T(Box::new(rng.next_u32()))
    }
}

struct R(u32);

impl Rng for R {
    fn next_u32(&mut self) -> u32 {
        let next = self.0;
        self.0 += 1;
        if self.0 > 10 {
            panic!();
        }
        next
    }
}
Run Code Online (Sandbox Code Playgroud)

基本上,如果有可能R触发恐慌并且T有一个析构函数,那么您将输入未定义的行为,因为数组的元素可能并非在该阶段都不会被初始化.Box<T>是这种未定义行为的一个特别好的例子,因为你将尝试释放未定义的内存地址.

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

或者(c)你可以使用矢量.

固定大小的数组目前是Rust的二等公民.