C++ 和 Java 中空类的大小是多少?为什么不是零?
sizeof();
在 C++ 的情况下返回 1。
8 回答
C++ 的简短答案:
C++ 标准明确规定类的大小不能为零。
C++ 的长答案:
因为每个对象都需要有一个唯一的地址(也在标准中定义),所以你不能真正拥有零大小的对象。
想象一个零大小的对象数组。因为它们的大小为零,所以它们都将排列在相同的地址位置。所以更容易说对象的大小不能为零。
笔记:
即使一个对象的大小不为零,如果它实际上占用了零空间,则不需要增加派生类的大小:
例子:
#include <iostream>
class A {};
class B {};
class C: public A, B {};
int main()
{
std::cout << sizeof(A) << "\n";
std::cout << sizeof(B) << "\n";
std::cout << sizeof(C) << "\n"; // Result is not 3 as intuitively expected.
}
g++ ty.cpp
./a.out
1
1
1
在 Java 案例中:
- 在 Java中没有简单的方法可以找出一个对象占用了多少内存。即没有
sizeof
运营商。 - 有几种方法(例如使用
Instrumentation
或 3rd 方库)会给你一个数字,但含义是微妙的1;请参阅在 Java 中,确定对象大小的最佳方法是什么? - 对象的大小(空或非空)是特定于平台的。
“空类”(即java.lang.Object
)的实例的大小不为零,因为该实例具有与其关联的隐式状态。例如,需要状态:
- 这样对象就可以用作原始锁,
- 表示其身份哈希码,
- 指示对象是否已完成,
- 引用对象的运行时类,
- 保存对象的 GC 标记位,
- 等等。
当前的 Hotspot JVM 使用巧妙的技巧来表示占用两个 32 位字的对象标头中的状态。(这在某些情况下会扩展;例如,当实际使用原始锁或identityHashCode()
调用 after 时。)
1 - 例如,由创建的字符串对象new String("hello")
的大小是否包括包含字符的支持数组的大小?从 JVM 的角度来看,该数组是一个单独的对象!
因为每个 C++ 对象都需要有一个单独的地址,所以不可能有一个大小为零的类(除了一些与基类相关的特殊情况)。C++中有更多信息:空类的对象的大小是多少?.
因为一个对象必须在内存中有一个地址,并且要在内存中有一个地址,它必须占用“一些”内存。因此,在 C++ 中,它通常是可能的最小数量,即 1 个字符(但这可能取决于编译器)。在 Java 中,我不太确定......它可能有一些默认数据(不仅仅是像 C++ 中的占位符),但如果它比 C++ 中的多得多,那将是令人惊讶的。
C++ 要求它的正常实例化的大小至少为 1(可能更大,尽管我不知道这样做的编译器)。但是,它允许“空基类优化”,因此即使该类的最小大小为 1,但当它用作基类时,它不必向派生类的大小添加任何内容。
我猜Java可能做的差不多。C++ 要求大小至少为 1 的原因是它要求每个对象都是唯一的。例如,考虑一个大小为零的对象数组。所有的对象都在同一个地址,所以你真的只有一个对象。让它为零听起来像是解决问题的秘诀……
它被 C++ 标准定义为“非零值”,因为分配的对象必须具有非零大小才能具有不同的地址。但是,从空类继承的类不需要增加大小,除非涉及到虚函数,通常会增加 vtable。
我不知道 java 中是否有 sizeof() 运算符。您可以做的是创建一个空类的实例(使其可序列化),通过 PipedOutputStream 发送它并将其作为字节数组读取 - byteArray.length 为您提供大小。
或者,使用 DataOutputStream 将实例写入文件,关闭文件,打开它,file.length() 将为您提供对象的大小。希望这会有所帮助,-MS