理解 Rust 中的枚举

问题描述 投票:0回答:3

我很难理解 Rust 中的

Enum
自定义类型。从广义上讲,The Book
Enum
描述为具有不同变体的自定义数据类型。我应该如何考虑这些变体?这些是子类型,还是
Enum
类型可以采用的特定值?

在网上查看我看到的例子如下:

enum Day {
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday,
    Sunday,
}

在上面的例子中,变体是

Day
类型的可能值。但在The Book中我们看到这样的例子:


struct Ipv4Addr {
    // --snip--
}

struct Ipv6Addr {
    // --snip--
}

enum IpAddr {
    V4(Ipv4Addr),
    V6(Ipv6Addr),
}

对我来说,

IpAddr::V4
似乎是一个子类型而不是特定值,但变量实际上是
IpAddr
类型并且可以有一个值
IpAddr::V4

我上面提到的区分有意义吗?

Enum
的正确解释是什么?

rust enums
3个回答
2
投票

Rust 是一种静态的强类型语言。它也非常快。在许多情况下,使用堆栈比堆更有效。但是,当您使用堆栈时,Rust 必须知道所需数据的大小。对于简单的固定类型(如

i16
u128
等)来说,这不是问题。对于元组、结构体或数组来说,这也不是问题,因为它们具有具有 known 大小的固定数据结构。

但是,有时您需要使用不同的数据类型,具体取决于某些运行时条件/状态。在 Java、.NET、JS、Python、PHP 等语言中,在这种情况下您将使用堆(以一种或另一种方式)。在 Rust 中,您也有使用堆的方法,但这通常不是最佳的。 Rust 中的枚举允许您使用自定义数据类型定义附加的、特定于变体的字段。这非常灵活,同时在许多情况下比使用堆的解决方案更快。

请注意,在像 Java 这样的语言中,您通常最终会创建类的层次结构来实现在 Rust 中使用枚举可以完成的操作。两种方法都有其优点和缺点。但如果您来自 Java 这样的语言,您应该记住这一点。

也许一个很好的例子是考虑如何用您选择的语言表示 JSON。如果 JSON 具有固定的数据结构,您可以使用 Rust 中的标准结构、Java 中的类等。但是如果您事先不知道 JSON 对象的结构怎么办?在大多数现代语言中,解析器会创建某种(链接的)HashMap,其中包含键的字符串和值的一些对象实例(整数、字符串、列表、映射等)。将其与

serde
Value
枚举进行比较。另一个例子是
mysql
Value
.

,它不适用于 JSON,但概念上相似,可以读取不同类型的数据。

了解 Rust 如何为枚举分配内存也可能很有用。它基本上确定(当然是在编译时)所有变体中哪一个需要最多的内存。假设变体

A
需要 12 个字节,变体
B
需要 16 个字节,变体
C
需要 4 个字节。 Rust 将为每个枚举实例的关联数据分配 16 个字节,因为这是所有变体可以容纳的最小大小。


0
投票

Day
视为 C 风格枚举是合理的。它描述了该类型的所有可能值,并有一个数字判别式来识别每个值。

IpAddr
类型是标记联合。它是一些标签(类似于 c 风格枚举中的数字),后跟您在括号中给出的值。它并不是真正的子类型,更多的是 IpAddr 的变体。

一旦被其标签识别(

match
等),您就可以使用里面的值。


0
投票

免责声明:我一生中从未写过一行 Rust,但作为一个 Rust 学习者,我是这样理解的:

Rust 枚举似乎是 C 枚举和联合的混合体。它们与联合相似,因为它们可以在同一个内存区域中存储不同类型的一份数据。与 C 联合相反,它们允许您查询联合中数据的类型。他们通过将这些信息存储在联合体旁边的称为鉴别器的东西中来做到这一点。

Rust 枚举类似于伪 C 中的以下内容:(语法可能是错误的,但你明白了。)

struct rust_union_t {
    enum {int,float} discriminator,
    union {int foo, float bar} data
}

在 C++ 中,您可以通过让

struct rust_union_t
提供两个构造函数来模拟这一点,一个采用 int,另一个采用 float。前者将
discriminator
设置为 int 并将值存储在
data
中,后者将
discriminator
设置为
float
并将值存储在
data
中。

在 Rust 中,编译器不会让你把这个写出来。


enum Day {
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday,
    Sunday,
}

这是 Rust 枚举的特殊情况,因为只有一个鉴别器,但没有要存储的实际值。


此链接帮助我理解:https://www.eventhelix.com/rust/rust-to- assembly-enum-match/

© www.soinside.com 2019 - 2024. All rights reserved.