loop和while之间有什么区别?

时间:2015-03-06 04:28:38

标签: loops rust

Rust教程,现在book声称while trueloop之间存在差异,但在此阶段理解它并不是非常重要。

  

如果你需要一个无限循环,你可能会写这个:

while true {
     

但是,Rust有一个专用的关键字loop来处理这种情况:

loop {
     

Rust的控制流分析对此构造的处理方式不同于一段时间,因为我们知道它将始终循环。在这个阶段,理解这些内容的细节并不是非常重要,但总的来说,我们可以为编译器提供的信息越多,它对安全性和代码生成的影响就越大,所以你应该总是更喜欢循环当你计划无限循环时。

完成了一些编译器类型的工作之后,我不得不想知道它有什么可能的语义差异,因为编译器弄清楚两者都是无限循环是微不足道的。

那么,编译器如何区别对待它们呢?

4 个答案:

答案 0 :(得分:18)

Reddit回答了这个问题。正如你所说,编译器可以是特例while true,但事实并非如此。因为它没有,编译器不会在语义上推断出在while true循环中设置的未声明变量必须始终在断开循环时进行初始化,而对于loop循环则必须初始化:

  

它还有助于编译器推理循环,例如

let x;
loop { x = 1; break; }
println!("{}", x)
     

完全有效,而

let x;
while true { x = 1; break; }
println!("{}", x);
     

无法使用指向x中的println的“使用可能未初始化的变量”进行编译。在第二种情况下,编译器没有检测到循环体总是至少运行一次。

     

(当然,我们可以在特殊情况下构造while true,就像loop一样。我相信这就是Java所做的。)

答案 1 :(得分:3)

一个主要区别是loop可以通过将值传递给breakreturn a valuewhilefor will not

fn main() {
    let mut counter = 0;

    let result = loop {
        counter += 1;

        if counter == 10 {
            break counter * 2;
        }
    };

    assert_eq!(result, 20);
}

答案 2 :(得分:2)

首先要说的是,就性能而言,这些可能是相同的。虽然Rust本身对while true没有做任何特殊处理,但LLVM可能会进行优化。 Rust编译器试图通过将优化委派给LLVM来保持简单。

  

一般来说,我们可以为编译器提供的信息越多,它对安全性和代码生成的影响就越大

虽然某些常量表达式可能会被LLVM优化掉,但语言的语义不会因表达式是否为常量而改变。这很好,因为它可以帮助人们更好地推理代码。

仅仅因为true是一个简单的表达式,我们知道它是常数。 true != false[0; 1].len() == 1也是如此。但是num_cpus::get() == 1呢?我实际上不知道是否有一些编译目标可以保持不变,我也不应该考虑它!

与生成的代码或宏结合使用时,telotortium's example中的错误会更加重要。想象一个宏有时会产生一个简单的静态表达式,如true == true,但有时引用变量或调用函数。有时编译器能够确定循环运行一次,但有时它不能运行。现在在Rust中,无论为该条件生成了什么代码,该示例中的错误都将始终成为错误。没有惊喜。

答案 3 :(得分:0)

  

loop和while之间有什么区别?

您可以问forwhile之间有什么区别?答案将接近:What is a programming idiom?

当你写while condition {}时,你说“条件为真,那就做”,但我们可以看到说“虽然这是真的,那样做”,是多余的。这是loop来自的地方,它可以非常好地表达无限循环,因为我们说“循环就在那”。我们没有任何条件,这是更好的。

  

那么,编译器如何区别对待它们呢?

我无法回答“如何”的问题,但我想你想知道“为什么”。它允许编译器知道此循环将至少运行一次,如来自C的do {} while (condition);。编译器可以使用此信息来生成更好的代码或警告。另外,您将确定循环将在while循环可能消失的情况下执行,因为编译器会对其进行优化。有趣的是,内部Rust使用LLVM,看起来LLVM没有办法表达无限循环,因此在某些情况下会生成bugs