我很难理解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
的正确解释是什么?
3条答案
按热度按时间ao218c7q1#
Rust是一种静态的强类型语言。它也非常快。在很多情况下,使用堆栈比堆更有效。然而,当你使用堆栈时,Rust * 必须 * 知道所需数据的大小。对于简单的固定类型,如
i16
,u128
等,这不是问题。对于元组,结构或数组,这也不是问题。因为它们有一个固定的数据结构和一个已知的大小。然而,有时候你需要使用不同的数据类型,这取决于一些运行时条件/状态。在Rust中,你也可以使用堆,但这通常不是最佳的。Rust中的枚举允许你定义额外的,变量特定的字段与自定义数据类型。这可以是非常灵活的,同时,在许多情况下,将比使用堆的解决方案更快。
请注意,在像Java这样的语言中,你通常会最终创建一个类的层次结构来实现你在Rust中使用枚举所能做的事情。这两种方法都有其优点和缺点。但是如果你来自像Java这样的语言,你应该记住这一点。
也许一个很好的例子是考虑如何用你选择的语言表示JSON。如果JSON有一个 * 固定 * 的数据结构,你可以使用Rust中的标准结构,Java中的类,等等。但是如果你事先不知道JSON对象的结构怎么办?在大多数现代语言中,解析器将创建某种(链接)HashMap,其中包含键和一些对象示例的字符串(整数、字符串、列表、Map等)。将其与
serde
的Value
枚举进行比较。另一个例子是mysql
的Value
,它不适用于JSON,但在概念上类似,因为您可以读取不同类型的数据。理解Rust如何为枚举分配内存可能也很有用。(当然是在编译时)在所有变体中,哪一个需要最多的内存。假设变体
A
需要12个字节,变体B
需要16个字节,变体C
需要4个字节。Rust将为每个枚举示例的关联数据分配16个字节,因为这是所有变体能容纳的最小尺寸。ie3xauqp2#
将
Day
视为C风格的枚举是合理的。它描述了该类型的所有可能值,并有一个数字判别式来识别每个值。IpAddr
类型是一个带标记的联合。它是一些标记(类似于c样式枚举中的数字),后跟在括号中给予的值。它不是真正的子类型,更像是IpAddr的变体。一旦通过它的标记(
match
等)识别出来,就可以使用里面的值了。lmvvr0a83#
免责声明:我一生中从未写过一行Rust,但作为一个Rust学习者,以下是我对它的理解:
Rust enum看起来像是C enum和union混合在一起。它们类似于union,因为它们可以在同一个内存区域中存储一段可以是不同类型的数据。与C union相反,它们允许您查询union中的数据的类型。它们通过将此信息存储在union旁边的一个名为descripminator的东西中来实现。
rust枚举类似于pseudo C中的以下内容:(pseudo可能是错误的,但您可以理解。
字符串
在C++中,你可以通过让
struct rust_union_t
提供两个构造函数来模拟这一点,一个接受int,另一个接受float。前者将discriminator
设置为int并将值存储在data
中,后者将discriminator
设置为float
并将值存储在data
中。在Rust中,编译器不会让你把它写出来。
型
这是rust枚举的特殊情况,因为只有一个值,但没有实际值要存储。
此链接帮助我理解:https://www.eventhelix.com/rust/rust-to-assembly-enum-match/