Rust教程,现在book声称while true
和loop
之间存在差异,但在此阶段理解它并不是非常重要。
如果你需要一个无限循环,你可能会写这个:
while true {
但是,Rust有一个专用的关键字loop来处理这种情况:
loop {
Rust的控制流分析对此构造的处理方式不同于一段时间,因为我们知道它将始终循环。在这个阶段,理解这些内容的细节并不是非常重要,但总的来说,我们可以为编译器提供的信息越多,它对安全性和代码生成的影响就越大,所以你应该总是更喜欢循环当你计划无限循环时。
完成了一些编译器类型的工作之后,我不得不想知道它有什么可能的语义差异,因为编译器弄清楚两者都是无限循环是微不足道的。
那么,编译器如何区别对待它们呢?
答案 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
可以通过将值传递给break
来return a value。 while
和for
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之间有什么区别?
您可以问for
和while
之间有什么区别?答案将接近:What is a programming idiom?
当你写while condition {}
时,你说“条件为真,那就做”,但我们可以看到说“虽然这是真的,那样做”,是多余的。这是loop
来自的地方,它可以非常好地表达无限循环,因为我们说“循环就在那”。我们没有任何条件,这是更好的。
那么,编译器如何区别对待它们呢?
我无法回答“如何”的问题,但我想你想知道“为什么”。它允许编译器知道此循环将至少运行一次,如来自C的do {} while (condition);
。编译器可以使用此信息来生成更好的代码或警告。另外,您将确定循环将在while
循环可能消失的情况下执行,因为编译器会对其进行优化。有趣的是,内部Rust使用LLVM,看起来LLVM没有办法表达无限循环,因此在某些情况下会生成bugs。