“如果”当条件为“假”时执行语句。在Rust程序中,如何理解? [英] "if" statement gets executed when the condition is "false" in a Rust program, how to understand it?

查看:123
本文介绍了“如果”当条件为“假”时执行语句。在Rust程序中,如何理解?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于以下Rust程序:

For the following Rust program:

fn main() {
    let foo = "test".to_string();
    if false {
        let _bar = foo; // value moved to _bar
    }
    println!("{}", foo);
}

运行该错误:

error[E0382]: borrow of moved value: `foo`
 --> src\main.rs:6:20
  |
2 |     let foo = "test".to_string();
  |         --- move occurs because `foo` has type `std::string::String`, which does not implement the `Copy` trait
3 |     if false {
4 |         let _bar = foo; // value moved to _bar
  |                    --- value moved here
5 |     }
6 |     println!("{}", foo);
  |                    ^^^ value borrowed here after move

移动后在这里借来的^^^价值有人能帮忙解释一下这里发生了什么吗?对我来说, move 发生在if语句中,这是永远不会正确的,这很奇怪。另外,我想进一步了解这种情况,应该使用哪些关键字搜索?

Could anyone help to explain what happens here? It's weird to me that the move happens in a if statement which will never be true. Also I want to know more about this situation, what keywords should I use to search?

推荐答案

这是的秘密移动:它们实际上并不存在。

Here's the secret to moves: they don't really exist.

移动不会生成与按位复制不同的代码(就机器代码而言)。移动和复制之间的唯一区别是原始文件会发生什么:如果仍然有效,则为复制文件;

Moves generate no code (in the sense of machine code) that is different from a bitwise copy.¹ The only difference between a move and a copy is what happens to the "original": if it's still valid, it's a copy; if the original is no longer valid, it's a move.

那么编译器如何强制您在移动后不使用原始值?没有运行时标志可以跟踪 foo 是否有效。而是,编译器使用源代码分析来确定在编译时 foo 是否绝对有效或在尝试使用它时是否已经移出了它。由于此分析是在编译时进行的,因此不会遵循函数内的执行流程;它同时针对整个功能发生。编译器发现 foo 已从 if 内部移出,并拒绝以后使用 foo 而不评估条件或任何代码。

So how does the compiler enforce that you don't use the original value after a move? There's no runtime flag that keeps track of whether foo is valid or not.² Instead, the compiler uses source code analysis to determine, at compile time, whether foo is definitely valid or may have been moved out of when you try to use it. Because this analysis takes place at compile time, it doesn't follow the flow of execution within the function; it happens for the whole function at once. The compiler sees that foo is moved out of inside the if, and rejects the later use of foo without evaluating the condition or any code.

智能编译器可以在执行时考虑控制流有效性分析,³但这可能不是一个改善。并非总是可能知道是否已采用分支机构(它是无法确定),因此在某些情况下编译器仍然会弄错的地方。而且,正如Cerberus在问题注释中指出的那样,这将大大减慢编译器的通过速度。

A smart compiler could take control flow into account when doing validity analysis,³ but that might not be an improvement. It's not always possible to know whether a branch is taken (it's undecidable), so there would be cases where the compiler would still get it wrong. Also, as Cerberus noted in the question comments, it would greatly slow down that compiler pass.

换句话说:在Rust中,您永远不会明确移动任何东西。您可以随心所欲地进行操作,然后根据类型是否为 Copy 以及以后是否使用它,让编译器告诉您是否做错了。这与C ++不同,在C ++中,移动是可以调用移动构造函数并具有副作用的操作。在Rust中,它是纯静态的通过/失败检查。如果操作正确,程序将继续进行并进入下一个编译阶段。如果您做错了,借用检查器会告诉您(并希望能帮助您解决问题)。

Put another way: In Rust, you never explicitly move something. You just do whatever you want with it, and let the compiler tell you whether you did it wrong or not, according to whether the type is Copy and whether it's used later. This is unlike C++, where moving is an operation that may call a "move constructor" and have side effects; in Rust, it's a purely static, pass/fail check. If you did it right, the program passes and moves on to the next stage of compilation; if you did it wrong, the borrow checker will tell you (and hopefully help you fix it).

  • What are move semantics in Rust?
  • Runtime vs Compile time

¹除非移动类型实现 Drop ,否则编译器可能会发出放置标志

¹ Unless the moved type implements Drop, in which case the compiler may emit drop flags.

²实际上,这里有 (放置标志),但仅在 foo 被删除时才检查,而不是在每次使用时检查。未实现 Drop 的类型即使具有相同的移动语义也没有删除标志。

² Actually, there is (the drop flag), but it's only checked when foo is dropped, not at each use. Types that don't implement Drop don't have drop flags, even though they have the same move semantics.

³这类似于Kotlin中的空检查工作原理:如果编译器可以确定引用绝对非空,则可以取消引用。 Rust中的有效性分析比这更保守。编译器甚至不会尝试猜测。

³ This is similar to how null checking works in Kotlin: if the compiler can figure out that a reference is definitely non-null, it will allow you to dereference it. Validity analysis in Rust is more conservative than that; the compiler doesn't even try to guess.

这篇关于“如果”当条件为“假”时执行语句。在Rust程序中,如何理解?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆