【问题标题】:A well supported alternative to c++ unions?一个受支持的 C++ 联合的替代方案?
【发布时间】:2018-10-02 01:53:12
【问题描述】:

我认为联合对于我的想法来说是完美的,尤其是当我认为我的代码应该在一个真正异构的机器系列上运行时,尤其是低功率机器,困扰我的是人们创建编译器的人似乎不太关心引入和提供良好的联合支持,例如this tableUnrestricted Unions 支持方面实际上是空的,这是一个真正令人不快的观点用于我的项目。

union 的替代品至少可以模仿相同的属性吗?

【问题讨论】:

  • @CodingMash 一种基于信号的系统,例如 SDL 系统,以及可以像经典 RGB 值示例一样“细分”的存储类型。
  • 您确定您了解您的需求吗?联合是 C 中一个非常古老的功能,并且在所有 C++ 编译器中都得到完全支持。 “不受限制的联合”是对联合的一种更改,是 C++11 中的新内容。阅读链接中从该表链接的包含的功能描述。

标签: c++ unions


【解决方案1】:

大多数编译器都很好地支持联合,但不支持的是包含具有非平凡构造函数的成员的联合(不受限制的联合)。实际上,在创建联合时几乎总是需要自定义构造函数,因此没有不受限制的联合会带来更多不便。

或者,您始终可以使用 void 指针指向具有足够大小的 malloc 内存以供最大成员使用。缺点是您需要显式类型转换。

【讨论】:

    【解决方案2】:

    联合的一个流行替代方案是Boost.Variant

    您在其中使用的类型必须是可复制构造的。

    更新: C++17 引入了std::variant。它的要求基于 Boost.Variant。它经过现代化改造以考虑 C++17 中的特性。它不承担与 C++98 编译器(如 Boost)兼容的开销。它随标准库免费提供。如果可用,最好将其用作联合的替代方案。

    【讨论】:

    • 在这种情况下,当我只需要压缩类型并使它们变得非常紧凑时,“模板”这个词听起来并不好;开发和调试模板也很痛苦。这个抽象级别的成本比它所能给我的要多。
    • 如果你想避免使用模板,那么你需要编写所有涉及的转换并手动进行类型检查。
    • @user1849534 你看过boost:variant 是如何使用的吗?它的内部是黑暗的模板魔法,但你不需要在使用它们时自己定义模板(但你当然可以)。见boost.org/doc/libs/1_52_0/doc/html/variant/…
    • @delnan 我对模板不过敏,“问题”是联合的好处是它以非常简单的方式工作,引入模板,这是最难的事情调试 + 另一个库,看起来不像是一个高级选择......
    • @user1849534:boost 变体的好处是它已经在许多编译器上进行了很好的测试,因此您可能高估了需要进行的测试和调试量。
    【解决方案3】:

    您总是可以使用显式强制转换来做同样的事情:

    struct YourUnion {
        char x[the size of your largest object];
        A &field1() { return *(A*)&x[0]; }
        int &field2() { return *(int*)&x[0]; }
    };
    
    YourUnion y;
    new(&y.field1()) A(); // construct A
    y.field1().~A(); // destruct A
    y.field2() = 1;
    // ...
    

    (与例如 Boost.Variant 相比,这是零开销。)

    编辑:更像联合并且没有模板。

    【讨论】:

    • 您需要确保存储正确对齐。
    • @user1849534:你不必使用模板……你可以每次都手写演员表。
    • @user1849534 为什么要避免使用模板?
    • 如果支持,请使用std::aligned_storage
    • @user1849534 如果您认为像最初显示的 ybungalobill 这样的简单模板太难调试,那么您也应该害怕不受限制的联合;与大多数 C++ 不同,您必须手动管理成员的生命周期,如果您弄错了,编译器不会告诉您,您只会得到未定义的行为。
    猜你喜欢
    • 2021-08-30
    • 2023-01-18
    • 2020-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多