【问题标题】:what is the size of empty class in C++,java?C++,java中空类的大小是多少?
【发布时间】:2011-01-25 04:14:39
【问题描述】:

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

【问题讨论】:

    标签: java c++ empty-class


    【解决方案1】:

    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
    

    【讨论】:

      【解决方案2】:

      在 Java 案例中:

      • 在Java 中没有简单 方法可以找出一个对象占用了多少内存;即没有sizeof 运算符。
      • 有几种方法(例如使用 Instrumentation 或 3rd 方库)会给您一个数字,但含义很微妙1;见In Java, what is the best way to determine the size of an object?
      • 对象的大小(空或非空)是特定于平台的。

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

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

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


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

      【讨论】:

        【解决方案3】:

        因为每个 C++ 对象都需要有一个单独的地址,所以不可能有一个大小为零的类(除了一些与基类相关的特殊情况)。 C++: What is the size of an object of an empty class? 有更多信息。

        【讨论】:

          【解决方案4】:

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

          【讨论】:

            【解决方案5】:

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

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

            【讨论】:

            • 我确信(可以推测)在某些时候我们会让它们具有更大的尺寸以帮助对齐或类似的东西。
            • @Martin:对齐仅在您要访问内存时才重要——但对于(概念上)零大小的对象,没有什么可访问的。我能想到它发生的唯一原因是一个实现(例如,Windows CE),其中 everything 的大小至少为 2 并且避免这种情况下的异常更方便(但这不是一个符合标准的实现,所以就标准 C++ 而言,它有点无关紧要)。
            • 几年前我第一次开始学习C++时,是用旧版的Borland C++编译器,我确实验证了一个空类的大小,它是4字节。从那以后,我一直认为它是 4 字节(或者平台的本机大小),但我不明白为什么它不能只是 1(因为它从未使用过)。我想人们每天都会在 C++ 中学到一些东西。
            • 标准要求非零大小,但没有规定大小。我可以想象,在需要指针保持某些特定对齐的平台中,该对齐将是空对象的大小,以便能够保持指向元素的唯一指针。在当前的英特尔架构中,这不是问题(您可以拥有指向内存中任何地址的指针),并且由于不会真正访问内存,因此出于性能原因,编译器不需要应用对齐。跨度>
            • @dribeas:好点——既然你提到了它,在 68000 上,即使尝试将奇数地址加载到地址寄存器中也会导致异常,所以我可以看到它在哪里有意义让它为空类使用 2 的大小。早期的 RISC 类似,但大多数需要 4 的倍数...
            【解决方案6】:

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

            【讨论】:

              【解决方案7】:

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

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

              【讨论】:

                【解决方案8】:

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

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

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2012-09-09
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2019-03-12
                  相关资源
                  最近更新 更多