【问题标题】:Possibly uninitialised variable from conditional可能来自条件的未初始化变量
【发布时间】:2021-05-12 18:58:08
【问题描述】:

我正在编写一个程序,它根据 CLI 标志将传入文件分成一个或两个输出文件。

至少它是这样工作的:

use std::{fs::File, io::Write};
fn main() {
    // Would be a CLI flag
    let write_all = true;

    let mut evens = File::create("evens.txt").expect("Nuh-uh");
    let mut odds: File;
    if write_all {
        odds = File::create("odds.txt").expect("Nuh-uh");
    }

    for i in 1..5 {
        if i % 2 == 0 {
            write!(&mut evens, "{}\n", i).expect("Can't write");
        } else {
            if write_all {
                write!(&mut odds, "{}\n", i).expect("Can't write");
            }
        }
    }
}

由于odds 在条件中创建时可能未初始化/超出范围,因此无法编译。

error[E0381]: borrow of possibly-uninitialized variable: `odds`
  --> src/main.rs:17:24
   |
17 |                 write!(&mut odds, "{}\n", i).expect("Can't write");
   |                        ^^^^^^^^^ use of possibly-uninitialized `odds`

error: aborting due to previous error

我已经看到 this answer 关于使用 Option<File>,但看不到如何将其应用于我的问题。

我考虑过的另一种选择是创建odds.txt 文件,如果!write_all 为真,则在最后删除它,但我不喜欢这种解决方案。

【问题讨论】:

  • 不是您的问题的答案,只是一个旁注:odds 确实在条件中初始化,但在编译时(应该)知道条件始终为真。我猜这里的编译器不是很聪明。
  • “但看不到如何将其应用于我的问题。” 那将是罪魁祸首。如果您仍然对此感到困惑,这本书有一个关于how the enum Option works 的部分。你能展示一下使用它的尝试吗?
  • @cornuz 该语言具有严格的语义,死代码并没有真正进入 that 方程。更不用说 OP 明确指出 write_all 只是为了演示的一个常量本地。
  • 不是将赔率作为文件,而是将其作为选项,而不是一直检查 write_all,而是检查选项是否为 Some(file)。
  • @E_net4thejanitor 谢谢你的指点,我想我现在明白了。如果有机会可以看看我的回答吗?

标签: rust


【解决方案1】:

使用Option<File>,您需要设置Some(File)None。然后要使用File,您需要将&mut Option<File> 解包到Option<&mut File>,这可以使用as_mut 或匹配odds 来完成。

use std::{fs::File, io::Write};
fn main() {
    // Would be a CLI flag
    let write_all = true;

    let mut evens = File::create("evens.txt").expect("Nuh-uh");
    let mut odds: Option<File>;
    if write_all {
        odds = Some(File::create("odds.txt").expect("Nuh-uh"));
    } else {
        odds = None;
    }

    for i in 1..5 {
        if i % 2 == 0 {
            write!(&mut evens, "{}\n", i).expect("Can't write");
        } else {
            if write_all {
                // let mut file = odds.as_mut().unwrap();
                // write!(&mut file, "{}\n", i).expect("Can't write");
                match odds {
                    Some(ref mut file) => write!(file, "{}\n", i).expect("Can't write"),
                    None => panic!("No file?"),
                }
            }
        }
    }
}

【讨论】:

  • 我会用一个 if Some(file) = &amp;mut file { ... 替换 if write_all / match odds
  • 第一个write_all条件也可以是let mut odds = write_all.then(|| File.create(...));
  • 这是一个使用字符串代替文件的完整版本:play.rust-lang.org/…
猜你喜欢
  • 2016-02-24
  • 2012-03-25
  • 2015-07-04
  • 1970-01-01
相关资源
最近更新 更多