Loops 循环和while true之间有什么区别?

Loops 循环和while true之间有什么区别?,loops,rust,Loops,Rust,Rust教程,现在声称while true和loop之间有区别,但是在这个阶段理解它并不是非常重要 如果您需要一个无限循环,您可能会尝试编写以下代码: while true { 但是,Rust有一个专门的关键字loop来处理这种情况: loop { Rust的控制流分析对待这个构造的方式与以前不同,因为我们知道它总是循环的。在这个阶段,理解这意味着什么的细节并不是非常重要,但一般来说,我们能给编译器提供的信息越多,它在安全性和代码生成方面就越好,所以当您计划无限循环时,您应该总是更喜欢循环

Rust教程,现在声称
while true
loop
之间有区别,但是在这个阶段理解它并不是非常重要

如果您需要一个无限循环,您可能会尝试编写以下代码:

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

loop {
Rust的控制流分析对待这个构造的方式与以前不同,因为我们知道它总是循环的。在这个阶段,理解这意味着什么的细节并不是非常重要,但一般来说,我们能给编译器提供的信息越多,它在安全性和代码生成方面就越好,所以当您计划无限循环时,您应该总是更喜欢循环

在做了一点编译器类型的工作之后,我不得不想知道可能存在什么语义差异,因为编译器很容易发现两者都是无限循环

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

这一点在上得到了回答。正如您所说,编译器可以使用特例
,而true
,但它不能。由于没有,编译器不会从语义上推断,如果中断循环,则在
while true
循环中设置的未声明变量必须始终初始化,而对于
循环
循环:

例如,它还帮助编译器对循环进行推理

let x;
loop { x = 1; break; }
println!("{}", x)
是完全有效的,而

let x;
while true { x = 1; break; }
println!("{}", x);
“使用可能未初始化的变量”指向
println
中的
x
,编译失败。在第二种情况下,编译器没有检测到循环体将至少运行一次

(当然,我们可以将构造
作为特例,而将true
作为
循环
的特例。我相信Java就是这样做的。)


首先要说的是,就性能而言,它们可能是相同的。虽然Rust本身对
没有任何特殊作用,而true则是
,但LLVM可能会进行这种优化。Rust编译器通过尽可能地将优化委托给LLVM来保持简单

一般来说,我们能给编译器提供的信息越多,它在安全性和代码生成方面就做得越好

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

因为
true
是一个简单的表达式,所以我们知道它是常量。
正确吗!=false
[0;1]。len()==1
。但是关于
num\u CPU::get()==1
呢?事实上,我不知道是否有一些编译目标可以是常数,我也不必考虑它

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

循环和while true之间有什么区别

您可以询问
for
while
之间的区别是什么?答案将接近于:

当你写
而条件{}
时,你说“当条件为真时,那么做”,但我们可以看到说“当条件为真时,那么做”是多余的。这就是
loop
的来源,它可以很好地表达无限循环,因为我们说“循环在那个上面”。我们没有任何条件,这样更好

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


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

一个主要区别是
循环
可以通过将值传递给
中断
来实现<代码>而
对于


谢谢,尽管这回避了一个问题:为什么?@aij几乎可以肯定,因为
而true
意味着可以将
true
提取到变量中或从函数返回,这会导致循环中断。不是一个好的开发经验。
fn main() {
    let mut counter = 0;

    let result = loop {
        counter += 1;

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

    assert_eq!(result, 20);
}