【问题标题】:How much memory do Enums take?枚举占用多少内存?
【发布时间】:2010-09-13 16:26:01
【问题描述】:

例如,如果我有一个包含两种情况的枚举,它是否比布尔值占用更多的内存?语言:Java、C++

【问题讨论】:

    标签: java c++ memory enums


    【解决方案1】:

    在 Java 中,enum is a full-blown class:

    Java 编程语言枚举类型 比他们强大得多 其他语言的对应物。这 枚举声明定义了一个类 (称为枚举类型)。枚举类 正文可以包括方法和其他 字段。

    为了查看每个enum 的实际大小,让我们创建一个实际的enum 并检查它创建的class 文件的内容。

    假设我们有以下Constants 枚举类:

    public enum Constants {
      ONE,
      TWO,
      THREE;
    }
    

    编译上述enum 并使用javap 反汇编生成的class 文件,得到以下结果:

    Compiled from "Constants.java"
    public final class Constants extends java.lang.Enum{
        public static final Constants ONE;
        public static final Constants TWO;
        public static final Constants THREE;
        public static Constants[] values();
        public static Constants valueOf(java.lang.String);
        static {};
    }
    

    反汇编显示enum 的每个字段都是Constants enum 类的实例。 (进一步分析javap会发现每个字段都是通过在静态初始化块中调用new Constants(String)构造函数来创建一个新对象来初始化的。)

    因此,我们可以看出,我们创建的每个 enum 字段至少与在 JVM 中创建对象的开销一样多。

    【讨论】:

    • 在 32 位平台上,它的大小与 int 完全相同——它只是一个(32 位)指向枚举实例的指针。每个枚举值在内存中只存在一个实例。
    • -1 “比普通整数重一点”?这是什么意思,你从文本中得到什么?
    【解决方案2】:

    在 ISO C++ 中,枚举没有义务大于其最大枚举数所需的大小。特别是,即使在 sizeof(bool)==sizeof(int) 时,枚举 {TRUE, FALSE} 也可能具有 sizeof(1)。根本没有要求。一些编译器使枚举与 int 大小相同。这是一个编译器特性,这是允许的,因为标准只规定了最低限度。其他编译器使用扩展来控制枚举的大小。

    【讨论】:

    • 我认为大多数 CPU 架构都使用原生大小。对于大多数 32 位 CPU,32 位对齐数据的检索速度很快,因此大多数类型最终都是 32 位的倍数。
    【解决方案3】:

    在 C/C++ 中,枚举的大小与 int 相同。

    使用 gcc,您可以将 attribute((packed)) 添加到枚举定义中,以使其占用最少的空间。如果枚举中的最大值

    typedef enum {
        MY_ENUM0,
        MY_ENUM1,
        MY_ENUM2,
        MY_ENUM3,
        MY_ENUM4,
        MY_ENUM5
    } __attribute__((packed)) myEnum_e;
    

    【讨论】:

    • 我很确定 __attribute__((packed)) 是一个仅限 GCC 的扩展。如果我没记错的话,C99 没有为“打包”指定标准编译指示,所以每个编译器的做法都不同。
    • 你可能是对的。在我的记忆中,packed 是 C99 的一个功能,但我的记忆常常是脾气暴躁和不合作的。我删除了 C99 引用。
    【解决方案4】:

    在 C++ 中,枚举的大小通常与 int 相同。也就是说,编译器提供命令行开关以允许将枚举的大小设置为适合定义的值范围的最小大小的情况并不少见。

    【讨论】:

      【解决方案5】:

      sizeof(enum) 取决于枚举中的内容。我最近试图使用默认构造函数参数查找 ArrayList() 的大小,并且内部没有存储对象(这意味着存储容量为 10)。原来ArrayList并没有太大

      因此,一个非常简单的枚举的 sizeof(enum) 应该小于 10 个字节。你可以写一个小程序,给它一定的内存,然后尝试分配枚举。你应该能弄明白(我就是这样找到ArrayList的内存的)

      BR,
      ~A

      【讨论】:

        【解决方案6】:

        只有在存储大量枚举时才会担心这一点。对于 Java,在某些情况下您可能可以使用 EnumSet。它在内部使用位向量,非常节省空间且速度快。

        http://java.sun.com/j2se/1.5.0/docs/api/java/util/EnumSet.html

        【讨论】:

          【解决方案7】:

          在 Java 中,每个枚举值在内存中应该只有一个实例。然后,对枚举的引用只需要该引用的存储空间。检查枚举的值与任何其他参考比较一样有效。

          【讨论】:

            【解决方案8】:

            bool 可以实现为单个字节,但通常在一个结构中,它会被具有对齐要求的其他元素包围,这意味着布尔值将有效地占用至少与int 一样多的空间.

            现代处理器从主内存加载数据作为整个高速缓存行,64 字节。从 L1 缓存加载一个字节和加载四个字节之间的差异可以忽略不计。

            如果您尝试优化高性能应用程序中的缓存行,那么您可能会担心枚举有多大,但通常我会说定义枚举比使用布尔值更清晰。

            【讨论】:

              【解决方案9】:

              如果您的枚举只有两种情况,那么确实使用布尔值可能是一个更好的主意(内存大小、性能、使用/逻辑),在 Java 中更是如此。
              如果您想知道内存成本,这可能意味着您计划使用大量内存。在 Java 中,您可以使用 BitSet 类,或者在较小的范围内,在这两种语言中,您都可以使用按位操作来操作位。

              【讨论】:

                【解决方案10】:
                printf("%d", sizeof(enum));
                

                【讨论】:

                  【解决方案11】:

                  在 Java 中,它会占用更多内存。在 C++ 中,它只占用相同类型的常量所需的内存(它在编译时评估,在运行时没有剩余意义)。在 C++ 中,这意味着枚举的默认类型将占用与 int 相同的空间。

                  【讨论】:

                    【解决方案12】:

                    不,枚举通常与 int 大小相同,与 boolean 相同。

                    【讨论】:

                    • 它可以,因此“一般”。但是,如果有人在没有进一步细节的情况下提出这样的问题,那么像这样的边缘情况很少重要。
                    • Java 和 C++ 标记表明此注释包含此上下文中的正确答案。
                    • 好的,经过进一步研究,Java 的答案似乎不正确。 (OT:不过,它与 C# 中的 int 相同。)
                    • 在 C++ 中枚举和 int 相同。 bool 和 char 相同。
                    猜你喜欢
                    • 1970-01-01
                    • 2014-05-11
                    • 1970-01-01
                    • 2017-02-06
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2010-11-25
                    相关资源
                    最近更新 更多