是否可以向编译器解释v
变量在标记为1
的行中是否合适,而不使用可能调用panic!
的不安全或代码?
#[derive(PartialEq, Debug)]
enum Enum {
V1,
V2,
V3,
}
fn main() {
let e = Enum::V1;
let mut v: i32;
if e == Enum::V1 || e == Enum::V2 {
v = 17; //some complex, costy expression
}
match e {
Enum::V1 | Enum::V2 => {
println!("Results: {}", v); //1
}
_ => {}
}
}
编译器报告:
error[E0381]: use of possibly uninitialized variable: `v`
--> src/main.rs:18:37
|
18 | println!("Results: {}", v); //1
| ^ use of possibly uninitialized `v`
我有一个复杂的表达式来初始化我的真实代码中的v
而不是17
,v
的类型没有实现Default
,我只需要{{ 1}}适用于v
和Enum::V1
个案例。
在实际代码中,我有Enum::V2
和Enum::V1
的单独分支,我可以在那里进行Enum::V2
初始化。
我想让我的代码更清晰,而且我不想使用v
或unsafe
答案 0 :(得分:5)
简单的方法是初始化v
;这是一个单词,如果没有必要,编译器可能会优化它。在这种特殊情况下,您甚至可以将声明和初始化都移动到匹配的内部范围中,因为它不会在其他任何地方使用。
更干净的事情是使无效案件无法代表。 v
仅在V1
或V2
的情况下才真正存在,因此如果我们加入这两个,我们就没有可能未初始化的值的名称。
#[derive(PartialEq, Debug)]
enum Enum {
V1 { v: i32 },
V2 { v: i32 },
V3
}
fn main() {
let mut e = Enum::V1 { v: 17 };
match e {
Enum::V1 {v} | Enum::V2 {v} => {
println!("Results: {}", v);//1
}
_ => {}
}
}
答案 1 :(得分:4)
在安全的Rust中,你不能。在您的代码中,v
仅保证在条件分支e == Enum::V1 || e == Enum::V2
下初始化,但v
在更广泛的范围内声明。请注意,这不是限制,而是来自编译器的提示,应该重新考虑程序的设计。
在这种情况下,我会将v
的计算委托给一个函数,并且在必要的案例块中只有v
。
fn calculate_v(e: Enum) -> i32 { ... }
let e = Enum::V1;
match e {
Enum::V1 => {
let v = calculate_v(e);
// use v
println!("Results: {}", v);//1
}
Enum::V2 => {
let v = calculate_v(e);
println!("Results: {}", v);//1
}
_ => {}
}