在Rust中理解枚举

ut6juiuv  于 9个月前  发布在  其他
关注(0)|答案(3)|浏览(125)

我很难理解Rust中的Enum自定义类型。从广义上讲,The BookEnum描述为具有不同变体的自定义数据类型。我应该如何看待这些变体?这些是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的正确解释是什么?

ao218c7q

ao218c7q1#

Rust是一种静态的强类型语言。它也非常快。在很多情况下,使用堆栈比堆更有效。然而,当你使用堆栈时,Rust * 必须 * 知道所需数据的大小。对于简单的固定类型,如i16u128等,这不是问题。对于元组,结构或数组,这也不是问题。因为它们有一个固定的数据结构和一个已知的大小。
然而,有时候你需要使用不同的数据类型,这取决于一些运行时条件/状态。在Rust中,你也可以使用堆,但这通常不是最佳的。Rust中的枚举允许你定义额外的,变量特定的字段与自定义数据类型。这可以是非常灵活的,同时,在许多情况下,将比使用堆的解决方案更快。
请注意,在像Java这样的语言中,你通常会最终创建一个类的层次结构来实现你在Rust中使用枚举所能做的事情。这两种方法都有其优点和缺点。但是如果你来自像Java这样的语言,你应该记住这一点。
也许一个很好的例子是考虑如何用你选择的语言表示JSON。如果JSON有一个 * 固定 * 的数据结构,你可以使用Rust中的标准结构,Java中的类,等等。但是如果你事先不知道JSON对象的结构怎么办?在大多数现代语言中,解析器将创建某种(链接)HashMap,其中包含键和一些对象示例的字符串(整数、字符串、列表、Map等)。将其与serdeValue枚举进行比较。另一个例子是mysqlValue,它不适用于JSON,但在概念上类似,因为您可以读取不同类型的数据。
理解Rust如何为枚举分配内存可能也很有用。(当然是在编译时)在所有变体中,哪一个需要最多的内存。假设变体A需要12个字节,变体B需要16个字节,变体C需要4个字节。Rust将为每个枚举示例的关联数据分配16个字节,因为这是所有变体能容纳的最小尺寸。

ie3xauqp

ie3xauqp2#

Day视为C风格的枚举是合理的。它描述了该类型的所有可能值,并有一个数字判别式来识别每个值。
IpAddr类型是一个带标记的联合。它是一些标记(类似于c样式枚举中的数字),后跟在括号中给予的值。它不是真正的子类型,更像是IpAddr的变体。
一旦通过它的标记(match等)识别出来,就可以使用里面的值了。

lmvvr0a8

lmvvr0a83#

免责声明:我一生中从未写过一行Rust,但作为一个Rust学习者,以下是我对它的理解:
Rust enum看起来像是C enum和union混合在一起。它们类似于union,因为它们可以在同一个内存区域中存储一段可以是不同类型的数据。与C union相反,它们允许您查询union中的数据的类型。它们通过将此信息存储在union旁边的一个名为descripminator的东西中来实现。
rust枚举类似于pseudo C中的以下内容:(pseudo可能是错误的,但您可以理解。

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/

相关问题