我有以下代码:
const N: usize = 10000;
const S: usize = 7000;
#[derive(Copy, Clone, Debug)]
struct T {
a: f64,
b: f64,
f: f64
}
fn main() {
let mut t: [T; N] = [T {a: 0.0, b: 0.0, f: 0.0}; N];
for i in 0..N {
t[i].a = 0.0;
t[i].b = 1.0;
t[i].f = i as f64 * 0.25;
}
for _ in 0..S {
for i in 0..N {
t[i].a += t[i].b * t[i].f;
t[i].b -= t[i].a * t[i].f;
}
println!("{}", t[1].a);
}
}
我不确定为什么必须以这种方式初始化数组t
。第一个for循环用于将包含struct的数组初始化为各自的值。
当我尝试直接用数组省略初始化时:
let mut t: [T; N];
我收到以下错误:
错误[E0381]:使用可能未初始化的变量:t
所有for循环都是这样的,我只是想知道数组是否有更聪明的方法,并且它是用第一个for循环初始化的。
答案 0 :(得分:7)
我不确定为什么必须以这种方式初始化数组
t
。
因为Rust不会让您(完全或部分)接触未初始化的值。编译器不够智能,无法证明循环肯定初始化所有内容,所以它只是禁止它。
现在,优化器是另一回事。 可以注意到初始化是多余的并且在理论上跳过它......它似乎没有使用该代码和当前编译器。这就是优化。
我只是想知道数组是否有更聪明的方法,并且使用第一个for循环进行初始化。
聪明的方法是让代码保持原样。从统计上讲,它不太可能成为瓶颈。如果分析表明 是瓶颈,那么您可以使用uninitialised
。但请注意,如果您使用错误,这样做会导致未定义的行为。虽然不是详尽的列表,但绝对可以避免在任何非Copy
的类型上使用它。
如果您需要使用它,我强烈建议您还调整第一个循环,以便忘记在结构中初始化元素或一个字段:
let mut t: [T; N] = unsafe { ::std::mem::uninitialized() };
for (i, e) in t.iter_mut().enumerate() {
*e = T {
a: 0.0,
b: 1.0,
f: i as f64 * 0.25,
}
}
答案 1 :(得分:2)
您可以使用std::mem::uninitialized()
。但请注意,它被认为是不安全的,需要标记为:
let mut t: [T; N] = unsafe { std::mem::uninitialized() };
如上述文件中所述:
这对FFI函数和初始化数组有时很有用, 但通常应该避免。