15

C++ 和 Java 中空类的大小是多少?为什么不是零? sizeof();在 C++ 的情况下返回 1。

4

8 回答 8

27

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
于 2011-01-25T04:18:06.317 回答
16

在 Java 案例中:

  • 在 Java中没有简单的方法可以找出一个对象占用了多少内存。即没有sizeof运营商。
  • 有几种方法(例如使用Instrumentation或 3rd 方库)会给你一个数字,但含义是微妙的1;请参阅在 Java 中,确定对象大小的最佳方法是什么?
  • 对象的大小(空或非空)是特定于平台的。

“空类”(即java.lang.Object)的实例的大小不为零,因为该实例具有与其关联的隐式状态。例如,需要状态:

  • 这样对象就可以用作原始锁,
  • 表示其身份哈希码,
  • 指示对象是否已完成,
  • 引用对象的运行时类,
  • 保存对象的 GC 标记位,
  • 等等。

当前的 Hotspot JVM 使用巧妙的技巧来表示占用两个 32 位字的对象标头中的状态。(这在某些情况下会扩展;例如,当实际使用原始锁或identityHashCode()调用 after 时。)


1 - 例如,由创建的字符串对象new String("hello")的大小是否包括包含字符的支持数组的大小?从 JVM 的角度来看,该数组是一个单独的对象!

于 2011-01-25T05:53:55.173 回答
4

因为每个 C++ 对象都需要有一个单独的地址,所以不可能有一个大小为零的类(除了一些与基类相关的特殊情况)。C++中有更多信息:空类的对象的大小是多少?.

于 2011-01-25T04:18:02.623 回答
4

因为一个对象必须在内存中有一个地址,并且要在内存中有一个地址,它必须占用“一些”内存。因此,在 C++ 中,它通常是可能的最小数量,即 1 个字符(但这可能取决于编译器)。在 Java 中,我不太确定......它可能有一些默认数据(不仅仅是像 C++ 中的占位符),但如果它比 C++ 中的多得多,那将是令人惊讶的。

于 2011-01-25T04:18:52.573 回答
3

C++ 要求它的正常实例化的大小至少为 1(可能更大,尽管我不知道这样做的编译器)。但是,它允许“空基类优化”,因此即使该类的最小大小为 1,但当它用作基类时,它不必派生类的大小添加任何内容。

Java可能做的差不多。C++ 要求大小至少为 1 的原因是它要求每个对象都是唯一的。例如,考虑一个大小为零的对象数组。所有的对象都在同一个地址,所以你真的只有一个对象。让它为零听起来像是解决问题的秘诀……

于 2011-01-25T04:21:05.993 回答
2

它被 C++ 标准定义为“非零值”,因为分配的对象必须具有非零大小才能具有不同的地址。但是,从空类继承的类不需要增加大小,除非涉及到虚函数,通常会增加 vtable。

于 2011-01-25T04:18:30.157 回答
0

我不知道 java 中是否有 sizeof() 运算符。您可以做的是创建一个空类的实例(使其可序列化),通过 PipedOutputStream 发送它并将其作为字节数组读取 - byteArray.length 为您提供大小。

或者,使用 DataOutputStream 将实例写入文件,关闭文件,打开它,file.length() 将为您提供对象的大小。希望这会有所帮助,-MS

于 2011-01-25T04:23:22.210 回答
0

正如其他人指出的那样,C++ 对象的大小不能为零。只有当它们充当不同类的子类时,类才能具有零大小。查看@Martin York 的答案以获取示例描述 - 并查看并投票在这方面正确的其他答案。

在 Java 中,在热点 VM中,每个对象有 2 个机器字(通常每个字 32 个拱形中的 4 个字节)的内存开销来保存簿记信息和运行时类型信息。对于数组,需要第三个字来保存大小。其他实现可以占用不同的内存量(经典的 Java VM,根据相同的引用,每个对象占用 3 个字)

于 2011-01-25T09:19:38.930 回答