【问题标题】:Why does Rust not have unions?为什么 Rust 没有工会?
【发布时间】:2015-03-25 06:13:28
【问题描述】:

我能想到 C 帮助中的许多地方都可以使用联合,它们可以节省内存。 Rust 是一种系统编程语言,为什么不支持联合?

【问题讨论】:

    标签: rust


    【解决方案1】:

    联合已添加到 (RFC 1444) 中的语言中,自 Rust 1.19.0 起它们是稳定的。它们需要使用 unsafe 块。

    原始联合不是内存安全的(因为编译器无法保证您始终从联合中读取正确的类型(即最近写入的类型))。 Rust 的目标之一是创建一种具有内存安全性的低级语言;由于联合与该目标不兼容,因此它们未包含在 Rust 1.0 中。

    相反,Rust 有 enums,它提供了联合的大部分优势以换取少量内存使用,但由于枚举值始终跟踪它包含的特定类型,因此它是内存安全的。

    【讨论】:

    • “换取一小块内存使用”,我只想补充一点,这个额外的内存只是标识符,1字节(只要不超过256个变体)。跨度>
    • @ReinF 虽然在实践中我希望额外的字节通常会被填充到机器字大小以提高效率。
    【解决方案2】:

    Rust 以代数数据类型的形式标记了联合enum:

    enum Foo {
        Bar(i32),
        Baz,
        Quux {
            misc: A,
            ellaneous: B,
            fields: C,
        },
    }
    

    Foo 可以是带有附加 i32Bar、没有附加数据的 Baz 或带有这三个杂项字段的 Quux。这是一个带标签的联合——枚举的大小不会超过它的最大变体加上标签所需的大小(通常是一个字节,但我想可能有比一个字节容纳的更多变体),并且在某些可以优化的情况下(例如Option<&T>,其中内存地址 0 对于Some 变体是不合法的,因此可用于表示None 变体)该变体被压缩到值中。


    Rust 中 not 所拥有的是 untagged 联合,就像在 C 中一样。 为什么?因为它们从根本上来说是不安全的,而安全对于 Rust 来说是最重要的。如果你仍然想要这样的东西,完全有可能围绕不安全的代码创建一个包装器,你最终会遇到像嬗变这样的事情,但在正常生活中你根本不需要未标记的联合。

    Rust确实现在支持未标记的联合作为不安全的概念; as of 1.19.0.

    【讨论】:

    • 标签可以大于一个字节,即使你只有两个变体(例如enum X { S(i32), U(u32) } 是八个字节),因为对齐。从技术上讲,它是一个字节加上三个字节的填充,但最终结果是一样的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-18
    • 2023-01-05
    • 1970-01-01
    • 2020-09-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多