【发布时间】:2015-03-25 06:13:28
【问题描述】:
我能想到 C 帮助中的许多地方都可以使用联合,它们可以节省内存。 Rust 是一种系统编程语言,为什么不支持联合?
【问题讨论】:
标签: rust
我能想到 C 帮助中的许多地方都可以使用联合,它们可以节省内存。 Rust 是一种系统编程语言,为什么不支持联合?
【问题讨论】:
标签: rust
联合已添加到 (RFC 1444) 中的语言中,自 Rust 1.19.0 起它们是稳定的。它们需要使用 unsafe 块。
原始联合不是内存安全的(因为编译器无法保证您始终从联合中读取正确的类型(即最近写入的类型))。 Rust 的目标之一是创建一种具有内存安全性的低级语言;由于联合与该目标不兼容,因此它们未包含在 Rust 1.0 中。
相反,Rust 有 enums,它提供了联合的大部分优势以换取少量内存使用,但由于枚举值始终跟踪它包含的特定类型,因此它是内存安全的。
【讨论】:
Rust 以代数数据类型的形式标记了联合,enum:
enum Foo {
Bar(i32),
Baz,
Quux {
misc: A,
ellaneous: B,
fields: C,
},
}
Foo 可以是带有附加 i32 的 Bar、没有附加数据的 Baz 或带有这三个杂项字段的 Quux。这是一个带标签的联合——枚举的大小不会超过它的最大变体加上标签所需的大小(通常是一个字节,但我想可能有比一个字节容纳的更多变体),并且在某些可以优化的情况下(例如Option<&T>,其中内存地址 0 对于Some 变体是不合法的,因此可用于表示None 变体)该变体被压缩到值中。
Rust 中 not 所拥有的是 untagged 联合,就像在 C 中一样。 为什么?因为它们从根本上来说是不安全的,而安全对于 Rust 来说是最重要的。如果你仍然想要这样的东西,完全有可能围绕不安全的代码创建一个包装器,你最终会遇到像嬗变这样的事情,但在正常生活中你根本不需要未标记的联合。
Rust确实现在支持未标记的联合作为不安全的概念; as of 1.19.0.
【讨论】:
enum X { S(i32), U(u32) } 是八个字节),因为对齐。从技术上讲,它是一个字节加上三个字节的填充,但最终结果是一样的。