关于rust:loop和while true有什么区别?

What is the difference between loop and while true?

Rust教程(现在预订)声称while trueloop之间有区别,但是在此阶段了解并不是非常重要。

If you need an infinite loop, you may be tempted to write this:

1
while true {

However, Rust has a dedicated keyword, loop, to handle this case:

1
loop {

Rust's control-flow analysis treats this construct differently than a while true, since we know that it will always loop. The details of what that means aren't super important to understand at this stage, but in general, the more information we can give to the compiler, the better it can do with safety and code generation, so you should always prefer loop when you plan to loop infinitely.

在完成了一些编译器类型的工作之后,我不得不想知道在语义上可能存在什么差异,因为对于编译器而言,找出两者都是无限循环将是微不足道的。

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


这在Reddit上得到了回答。如您所说,编译器可以对while true作特例,但事实并非如此。既然没有,编译器不会从语义上推断出,如果您退出循环,则必须始终初始化在while true循环内设置的未声明变量,而对于loop循环则必须进行初始化:

It also helps the compiler reason about the loops, for example

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

is perfectly valid, while

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

fails to compile with"use of possibly uninitialised variable" pointing to the x in the println. In the second case, the compiler is not detecting that the body of the loop will always run at least once.

(Of course, we could special case the construct while true to act like loop does now. I believe this is what Java does.)


首先要说的是,就性能而言,它们可能是相同的。尽管Rust本身对while true并没有做任何特别的事情,但LLVM可能确实使这种优化成为可能。 Rust编译器通过将优化委托给LLVM来尝试使事情变得简单。

in general, the more information we can give to the compiler, the better it can do with safety and code generation

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

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

当与生成的代码或宏结合使用时,telotortium的示例中的错误将更加严重。想象一下一个宏,它有时会导致一个简单的静态表达式,例如true == true,但有时会引用一个变量或调用一个函数。有时,编译器能够确定循环运行一次,而其他时候则无法。现在在Rust中,无论为该条件生成了什么代码,该示例中的错误始终都是错误。没什么好奇怪的


一个主要区别是loop可以通过将值传递给break来返回值。 whilefor不会:

1
2
3
4
5
6
7
8
9
10
11
12
13
fn main() {
    let mut counter = 0;

    let result = loop {
        counter += 1;

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

    assert_eq!(result, 20);
}

What is the difference between loop and while true?

您可能会问forwhile有什么区别?答案将接近:什么是编程习惯用法?

当您编写while condition {}时,您说"条件成立时,执行此操作",但是我们可以看到"条件成立时,执行此操作"是多余的。这就是loop的来源,它可以很好地表示无限循环,因为我们说"循环在那"。我们没有任何条件,这更好。

So, how does the compiler treat them differently?

我无法回答"如何"的问题,但我想您想知道"为什么"。它使编译器知道该循环将至少运行一次,如C中的do {} while (condition);。编译器可以使用此信息来生成更好的代码或警告。另外,您可以确定该循环将在while循环消失的地方执行,因为编译器对其进行了优化。有趣的是,Rust内部使用LLVM,并且LLVM似乎没有表达无限循环的方法,因此在某些情况下会产生错误。