例如,如果我有一个有两种情况的枚举,它是否比布尔值占用更多的内存?语言:Java、C++
12 回答
在 Java 中,anenum
是一个成熟的类:
Java 编程语言的枚举类型比其他语言中的枚举类型强大得多。枚举声明定义了一个类(称为枚举类型)。枚举类主体可以包括方法和其他字段。
为了查看每个 的实际大小enum
,让我们创建一个实际的enum
并检查class
它创建的文件的内容。
假设我们有以下Constants
枚举类:
public enum Constants {
ONE,
TWO,
THREE;
}
编译上述内容enum
并反汇编生成的class
文件javap
给出以下内容:
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 {};
}
反汇编表明 an 的每个字段都是该类enum
的一个实例Constants
enum
。(进一步分析javap
会发现每个字段都是通过调用new Constants(String)
静态初始化块中的构造函数来创建一个新对象来初始化的。)
因此,我们可以看出enum
,我们创建的每个字段至少与在 JVM 中创建对象的开销一样多。
在 Java 中,每个枚举值在内存中应该只有一个实例。然后,对枚举的引用只需要该引用的存储。检查枚举的值与任何其他参考比较一样有效。
只有在存储大量枚举时才会担心这一点。对于 Java,在某些情况下您可以使用 EnumSet。它在内部使用一个位向量,非常节省空间且速度很快。
http://java.sun.com/j2se/1.5.0/docs/api/java/util/EnumSet.html
bool
可以实现为单个字节,但通常在结构中它会被具有对齐要求的其他元素包围,这意味着布尔值将有效地占用至少与int
.
现代处理器从主存加载数据作为整个高速缓存行,64 字节。从 L1 缓存加载一个字节和加载四个字节之间的差异可以忽略不计。
如果您正在尝试优化高性能应用程序中的缓存行,那么您可能会担心枚举有多大,但通常我会说定义枚举比使用布尔值更清楚。
在 Java 中,它会占用更多内存。在 C++ 中,它不会占用相同类型的常量所需的内存(它在编译时评估并且在运行时没有剩余意义)。在 C++ 中,这意味着枚举的默认类型将占用与 int 相同的空间。
在 ISO C++ 中,枚举没有义务大于其最大枚举数所需的大小。特别是,即使在 sizeof(bool)==sizeof(int) 时,枚举 {TRUE, FALSE} 也可能具有 sizeof(1)。根本没有要求。一些编译器使枚举与 int 大小相同。这是一个编译器特性,这是允许的,因为标准只规定了最低限度。其他编译器使用扩展来控制枚举的大小。
printf("%d", sizeof(enum));
在 C++ 中,枚举通常与int
. 也就是说,编译器提供命令行开关以允许将枚举的大小设置为适合定义的值范围的最小大小的情况并不少见。
不,枚举通常与 int 大小相同,与布尔值相同。
如果您的枚举只有两种情况,那么确实使用布尔值可能是一个更好的主意(内存大小、性能、使用/逻辑),在 Java 中甚至更多。
如果您想知道内存成本,这可能意味着您计划使用大量内存。在 Java 中,您可以使用 BitSet 类,或者在更小的范围内,在这两种语言中,您都可以使用按位操作来操作位。
sizeof(enum) 取决于枚举中的内容。我最近试图使用默认构造函数参数查找 ArrayList() 的大小,并且内部没有存储对象(这意味着存储容量为 10)。原来 ArrayList 并没有太大 < 100 字节。
因此,一个非常简单的枚举的 sizeof(enum) 应该小于 10 个字节。你可以写一个小程序,给它一定的内存,然后尝试分配枚举。你应该能够弄清楚(这就是我发现ArrayList的内存的方式)
BR,
~A
在 C/C++ 中,枚举的大小与 int 相同。
使用 gcc,您可以将属性((packed)) 添加到枚举定义中,以使其占用最小的空间。如果枚举中的最大值 < 256,这将是一个字节,如果最大值是 < 65536,则为两个字节,等等。
typedef enum {
MY_ENUM0,
MY_ENUM1,
MY_ENUM2,
MY_ENUM3,
MY_ENUM4,
MY_ENUM5
} __attribute__((packed)) myEnum_e;