为什么在Rust中必须初始化结构体?

3
在C语言中,我可以使用一个未初始化的结构体。我在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中会出现错误?

5
不同的编程语言有不同的特点。例如在C语言中,可以创建一个结构体而不进行初始化,但是它的成员将具有"不确定"的值,使用它们可能会导致"未定义行为"。关于Rust在这方面的工作原理我不清楚,它可能完全不同。这是直接比较编程语言之间的难点之一,即使它们对某些结构具有相似的语法。 - undefined
1
你还没有将user1定义为User类型,请尝试使用let mut user1 = User或者let mut user1 = User(user, email, login_count, active)。可以参考这个链接中的示例。 - undefined
在Rust中,未初始化的变量是绝对存在的,但你要么必须稍后以一种编译器可以保证在使用之前初始化的方式来结构化初始化,要么深入到std::mem::MaybeUninit的领域以非正常的方式进行初始化。即使如此,如果你没有正确操作,仍然会出现未定义行为 - undefined
2个回答

14

Rust中的所有值如果要安全地访问,都必须有一个初始化的值。

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

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

在C中,您可以访问那些未初始化的值;从而允许编译器错误地编译您的代码,因为您已经违反了契约。然而,在Rust中,您不能这样做。

在某些语言中,例如C#,您可以使用null替换未初始化的值。我们有一个类似的概念:Option,它们可以是Some(value)或者是None


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


虽然有办法达到C语言的效果,但是这些方法被称为unsafe,强烈建议在日常操作中避免使用,所以在尝试不必要的unsafe和可能出现不稳定行为之前,请尽最大努力寻找其他解决方案。

在涉足unsafe之前,请使用std::mem :: MaybeUninit并阅读Rust nomicon


1
根据Rust文档,即使使用MaybeUninit,目前仍然没有安全的方法逐个字段初始化结构体 - undefined

5
正如Optimistic Peach所说,这主要是Rust的工作方式。在Rust中,所有东西都需要被初始化。每个变量也是如此。
但是Rust之所以这样做并不是编译器的问题。从C语言中你知道,即使变量没有被初始化,编译器也可以编译代码而没有问题。问题在于,如果只定义了一个变量而没有初始化它,这个变量可以被访问,其值将是存储变量的内存位置中已经存在的任何内容。
Rust试图成为一种非常安全的语言。访问未初始化的内存经常是错误的原因,因此它确实想要防止这种情况发生。设计师们本可以选择使用一些默认值来代替程序代码中没有提供默认值的情况,但他们决定始终要求明确的默认值。 ——这基本上只是他们做出的一种设计选择。
这种设计选择的原因可能是,在Rust中有几种类型,其中没有明显的默认值。在其他语言中,如C#,您有可以分配给所有引用的null值。在Rust中,您可以通过使用Option 作为类型(而不仅仅是T)并分配None值来获得类似于null的东西。但是,只有当程序员决定使用Option 而不是T时,才会起作用。如果没有null并且程序员没有定义初始值,那么类型为std::fs::File的变量的默认值是什么呢?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接