0

在 CI 中可以使用尚未初始化的结构。我在 Rust 中尝试了这段代码:

struct User {
    username: String,
    email: String,
    sign_in_count: u64,
    active: bool,
}

fn main(){
    let mut user1: User;
    user1.active = false;
}

但它产生了编译错误:

error[E0381]: assign to part of possibly-uninitialized variable: `user1`
  --> src/main.rs:10:5
   |
10 |     user1.active = false;
   |     ^^^^^^^^^^^^^^^^^^^^ use of possibly-uninitialized `user1`

为什么这在 C 中是允许的,但在 Rust 中是错误的?

4

2 回答 2

10

如果要安全地访问 Rust 中的所有值,它们必须具有初始化值。

这是因为使用未初始化值的操作具有未定义的行为。这可能导致编译器意外错误编译您的代码。

避免错误编译是 Rust 的主要目标之一。包括其他形式的未定义行为,例如数据竞争、取消引用无效指针或更改其他代码假定不会更改的数据。在这里阅读更多。

在 C 中,您可以访问这些值;从而允许编译器错误编译您的代码,因为您违反了合同。然而,在 Rust 中,你不能这样做。

在某些语言中,例如 C#,您将未初始化的值替换为null. 我们有一个类似的概念:Options,要么是要么Some(value)None


请注意,如果编译器由于与不健全的操作相关的未定义行为而错误编译了您的代码,这不是编译器的错。它也没有试图寻找这个。它只是试图优化您的代码。如果我给你一个棒球棒,你用它来敲你的头,那你就是在滥用它,这不是我的错,作为一个设计师,因为我无法预见你会滥用它。


不过,有一些方法可以做你在 C 中可以做的事情。但是,对于常规操作,强烈建议不要使用这些方法,因此请在陷入不必要且可能不合理的行为unsafe之前尽最大努力寻找另一种解决方案。unsafe

涉足. _ std::mem::MaybeUninit_ _unsafe

于 2020-04-17T04:52:51.920 回答
3

正如 Optimistic Peach 所说,这主要是 Rust 的工作方式。一切都需要在 Rust 中初始化。其他所有变量也一样。

但是 Rust 这样做的原因并不是编译器的问题。正如您从 C 中知道的那样,即使变量没有被初始化,那里的编译器也可以毫无问题地编译代码。问题是,如果您只定义一个变量而不对其进行初始化,则可以访问该变量,并且该值将是该变量存储在内存位置中的任何值。

Rust 试图成为一种非常安全的语言。访问未初始化的内存通常是导致错误的原因,因此它确实希望防止这种情况发生。当程序代码中没有给出默认值时,设计人员本可以选择使用一些默认值,但他们决定始终要求明确的默认值。——这或多或少只是他们所做的设计选择。

选择这种设计的原因可能是在 Rust 中有几种类型,其中没有明显的默认值。在 C# 等其他语言中,您拥有null可以分配给所有引用的值。null在 Rust 中,您可以使用类似于Option<T>类型(而不仅仅是 T)并分配None值。但这只有在程序员决定使用Option<T>而不仅仅是T. std::fs::File如果nullRust 中没有并且程序员没有定义初始值,那么类型变量的默认值是多少?

于 2020-04-17T06:26:01.070 回答