ear*_*283 0 c initialization rust memory-safety
在 CI 中可以使用尚未初始化的结构体。我在 Rust 中尝试过这段代码:
struct User {
username: String,
email: String,
sign_in_count: u64,
active: bool,
}
fn main(){
let mut user1: User;
user1.active = false;
}
Run Code Online (Sandbox Code Playgroud)
但它产生了一个编译错误:
error[E0381]: assign to part of possibly-uninitialized variable: `user1`
--> src/main.rs:10:5
|
10 | user1.active = false;
| ^^^^^^^^^^^^^^^^^^^^ use of possibly-uninitialized `user1`
Run Code Online (Sandbox Code Playgroud)
为什么这在 C 中是允许的,但在 Rust 中是错误的?
Opt*_*ach 10
如果要安全访问 Rust 中的所有值,则必须有一个初始化值。
这是因为使用未初始化值的操作具有未定义的行为。这可能导致编译器意外错误编译您的代码。
避免错误编译是 Rust 的主要目标之一。包括其他形式的未定义行为,例如数据竞争、取消引用无效指针或更改其他代码假定不会更改的数据。在这里阅读更多。
在 C 中,您可以访问这些值;因此,由于您违反了合同,因此允许编译器错误编译您的代码。但是,在 Rust 中,您不允许这样做。
在某些语言(例如 C#)中,您将未初始化的值替换为null
. 我们有一个类似的概念:Option
s,要么是要么Some(value)
有None
。
请注意,如果编译器由于与不健全操作相关的未定义行为而错误编译了您的代码,这不是编译器的错。它也不是试图寻找这个;它只是试图优化您的代码。如果我给你一个棒球棒,你用它来敲你的头,那你就是在滥用它,这不是我作为设计师的错,因为我无法预见你会滥用它。
有一些方法可以做你可以在 C 中做的事情。这些都是unsafe
和强烈不赞成为常规操作的,所以请尽你最大努力寻找跳跃之前的另一个解决方案到不必要unsafe
和不合理的可能行为。
使用std::mem::MaybeUninit
和阅读锈nomicon在涉足之前unsafe
。
正如 Optimistic Peach 已经说过的,这主要就是 Rust 的工作方式。一切都需要在 Rust 中初始化。其他所有变量也是如此。
\n\n但 Rust 之所以这么做,并不是编译器的问题。正如您从 C 中知道的那样,即使变量没有初始化,那里的编译器也可以毫无问题地编译代码。问题是,如果您只是定义一个变量而不对其进行初始化,则可以访问该变量,并且该值将是该变量存储的内存位置中已有的值。
\n\nRust 试图成为一种非常安全的语言。访问未初始化的内存通常是导致错误的原因,因此它确实希望防止这种情况发生。当程序代码中没有给出默认值时,设计者可以选择使用一些默认值,但他们决定始终需要显式默认值。\xe2\x80\x94这或多或少只是他们所做的设计选择。
\n\n这种设计选择的原因可能是 Rust 中有多种类型,但没有明显的默认值。在其他语言(如 C#)中,您null
可以将值分配给所有引用。在 Rust 中,您可以使用类似的东西null
作为Option<T>
类型(而不仅仅是 T)并分配值None
。但这仅在程序员决定使用Option<T>
而不是仅使用时才有效T
。std::fs::File
如果 Rust 中没有类型变量null
并且程序员没有定义初始值,那么该类型变量的默认值可能是什么?