If statement &引用;如果;语句在条件为“时执行”;假;在生锈程序中,如何理解它?

If statement &引用;如果;语句在条件为“时执行”;假;在生锈程序中,如何理解它?,if-statement,scope,rust,borrowing,If Statement,Scope,Rust,Borrowing,对于以下防锈程序: fn main(){ 让foo=“test”。to_string(); 如果错误{ 让_bar=foo;//值移动到_bar } println!(“{}”,foo); } 我在运行它时遇到此错误: 错误[E0382]:移动值的借用:`foo` -->src\main.rs:6:20 | 2 | let foo=“test.”to_string(); |---发生移动是因为'foo'的类型为'std::string::string',而该类型不实现'Copy'特性 3 |如

对于以下防锈程序:

fn main(){
让foo=“test”。to_string();
如果错误{
让_bar=foo;//值移动到_bar
}
println!(“{}”,foo);
}
我在运行它时遇到此错误:

错误[E0382]:移动值的借用:`foo`
-->src\main.rs:6:20
|
2 | let foo=“test.”to_string();
|---发生移动是因为'foo'的类型为'std::string::string',而该类型不实现'Copy'特性
3 |如果为假{
4 |让_bar=foo;//值移动到_bar
|---值移到了这里
5 |     }
6 | println!(“{}”,foo);
|^^^移动后在此借用的值
有人能解释一下这里发生了什么吗?我觉得奇怪的是,移动发生在一个if语句中,这个语句永远不会是真的。另外,我想知道更多关于这种情况的信息,我应该使用什么关键字来搜索?

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

移动不会生成与按位复制不同的代码(在机器代码的意义上)。移动和复制之间的唯一区别在于“原始”的情况:如果它仍然有效,则它是一个副本;如果原件不再有效,则为移动

那么,编译器如何强制您在移动后不使用原始值呢?没有跟踪
foo
是否有效的运行时标志。相反,编译器在编译时使用源代码分析来确定
foo
是否确实有效,或者在您尝试使用它时是否已被移出。因为这种分析是在编译时进行的,所以它不遵循函数内的执行流程;整个函数同时发生。编译器看到
foo
被移出
if
的内部,并拒绝以后使用
foo
,而不评估条件或任何代码

智能编译器在进行有效性分析时可以考虑控制流,但这可能不是一种改进。不可能总是知道是否执行了一个分支,因此在某些情况下编译器仍然会出错。此外,正如Cerberus在问题评论中所指出的,这将大大降低编译器通过的速度

换句话说:在锈迹斑斑的环境中,你永远不会明确地移动某些东西。您只需根据类型是否为
Copy
以及是否在以后使用,对其执行任意操作,然后让编译器告诉您是否做错了。这与C++不同,其中移动是一种操作,可以称为“移动构造函数”并具有副作用;在Rust中,这是一个纯静态的通过/失败检查。如果你做对了,程序就会通过并进入下一个编译阶段;如果你做错了,借钱人会告诉你(希望能帮你解决)

另见

除非移动的类型实现了
Drop
,在这种情况下,编译器可能会发出

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

这与Kotlin中的null检查工作原理类似:如果编译器能够确定引用肯定是非null的,那么它将允许您取消引用它。Rust的有效性分析较保守;编译器甚至不尝试猜测。

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

移动不会生成与按位复制不同的代码(在机器代码的意义上)。移动和复制之间的唯一区别在于“原始”的情况:如果它仍然有效,则它是一个副本;如果原件不再有效,则为移动

那么,编译器如何强制您在移动后不使用原始值呢?没有跟踪
foo
是否有效的运行时标志。相反,编译器在编译时使用源代码分析来确定
foo
是否确实有效,或者在您尝试使用它时是否已被移出。因为这种分析是在编译时进行的,所以它不遵循函数内的执行流程;整个函数同时发生。编译器看到
foo
被移出
if
的内部,并拒绝以后使用
foo
,而不评估条件或任何代码

智能编译器在进行有效性分析时可以考虑控制流,但这可能不是一种改进。不可能总是知道是否执行了一个分支,因此在某些情况下编译器仍然会出错。此外,正如Cerberus在问题评论中所指出的,这将大大降低编译器通过的速度

换句话说:在锈迹斑斑的环境中,你永远不会明确地移动某些东西。您只需根据类型是否为
Copy
以及是否在以后使用,对其执行任意操作,然后让编译器告诉您是否做错了。这与C++不同,其中移动是一种操作,可以称为“移动构造函数”并具有副作用;在Rust中,这是一个纯静态的通过/失败检查。如果你做对了,程序就会通过并进入下一个编译阶段;如果你做错了,借钱人会告诉你(希望能帮你解决)

另见

除非移动的类型实现了
Drop
,在这种情况下,编译器可能会发出

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

这类似于