C++:空类对象的大小是多少?

Ash*_*ppa 105 c++ class object

我想知道一个空类的对象大小.它肯定不能是0字节,因为它应该可以像任何其他对象一样引用和指向它.但是,这样的对象有多大?

我用过这个小程序:

#include <iostream>
using namespace std;

class Empty {};

int main()
{
    Empty e;
    cerr << sizeof(e) << endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我在Visual C++和Cygwin-g ++编译器上得到的输出是1个字节!这对我来说有点令人惊讶,因为我期望它的机器字大小(32位或4字节).

任何人都可以解释为什么 1字节的大小?为什么不是 4个字节?这是依赖于编译器还是机器?此外,有人可以给出一个更有说服力的理由,说明为什么空类对象的大小不是 0字节?

Sol*_*Sol 124

引用Bjarne Stroustrup的C++样式和技术FAQ,大小非零的原因是"确保两个不同对象的地址不同." 并且大小可以是1,因为在这里对齐并不重要,因为实际上没有什么可以看.

  • 呸,他对C++有什么了解?:-) (54认同)
  • @Lazer,因为C中没有空结构. (17认同)
  • @nurabha this指针指向*对象*.它没有存储在对象中.但是,如果存在虚函数,则该对象包含指向vtable的指针. (7认同)
  • @krish_oza:你认为错了.在堆栈上分配变量时,它不能占用零字节(因为不同的变量需要不同的地址),因此最小值为1.之后,由编译器决定.与`new`类似; 在分配空间时,另一个分配必须具有不同的地址.等等.空类中不一定涉及任何指针; 可能存在指向变量(或引用或本地/堆栈分配)的指针,但它们不是零大小,并且它们不一定是指针大小. (4认同)
  • @Destructor,并不聪明,但我确实知道笑容是什么:-)你可能想重新阅读评论,并认识到这是幽默. (3认同)

Tra*_*Man 30

该标准规定所有派生的对象都具有sizeof()> = 1:

除非它是位字段(class.bit),否则大多数派生对象应具有非零大小并且应占用一个或多个存储字节.基类子对象可以具有零大小. ISO/IEC FDIS 14882:1998(E)intro.object

  • @eSKay - 这是必需的,以便不同的对象获得不同的地址.您不能拥有指向对象的指针映射,例如,如果不同的实例具有相同的地址. (4认同)

pax*_*blo 13

这真的是一个实现细节.很久以前,我认为它可能是零字节或一千字节,它与语言规范无关.但是,在查看标准(第5.3.3节)之后,sizeof定义为总是返回一个或更大,无论如何.

最派生类的大小应大于零.

除其他外,这是允许您处理对象数组和指向它们的指针所必需的.如果你的元素被允许为零大小,那么它们&(array[0])将是相同的&(array[42]),这将对你的处理循环造成各种各样的破坏.

它可能不是机器字的原因是它内部没有实际要求它在字边界上对齐的元素(例如整数).例如,如果放在char x; int y;类中,我的GCC将其计时为8个字节(因为第二个int必须在该实现中对齐).

  • @BrianNeal,这没问题,因为他们没有状态来区分自己。只有当您考虑指针时,问题才会出现。 (2认同)
  • 或者采用所述数组的大小来计算其长度. (2认同)

Kon*_*tin 6

有一个例外:0长度数组

#include <iostream>

class CompletlyEmpty {
  char NO_DATA[0];
};

int main(int argc, const char** argv) {
  std::cout << sizeof(CompletlyEmpty) << '\n';
}
Run Code Online (Sandbox Code Playgroud)

  • C和C++不允许零长度数组.你的编译器可以,但它是不正确的. (5认同)
  • 这实际上不是有效的 C++。根据声明数组的 C++20 标准,`[dcl.array]`:“如果存在常量表达式,则它应是类型为 `std::size_t` 的转换后的常量表达式,并且***其值应为大于零***。” (2认同)

小智 5

即使它不需要为空类分配任何内存,但为了使空类的对象,编译器分配可分配的最小内存,即1个字节.这样,编译器可以唯一地区分同一空类的两个对象,并且能够将对象的地址分配给空类类型的指针.