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

我想知道什么是 size of an object of an empty class。它肯定可以 没有为0字节,因为它应该可以像其他对象一样引用和指向它。但是,这样一个物体有多大呢?

我用了这个小程序:

#include <iostream>
using namespace std;


class Empty {};


int main()
{
Empty e;
cerr << sizeof(e) << endl;
return 0;
}

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

有人能解释一下 why的1字节大小吗?为什么不呢4字节?这也依赖于编译器还是机器?另外,是否有人可以给出一个更有说服力的理由来解释为什么空类对象 不会的大小为0字节?

73398 次浏览

这实际上是一个实现细节。很久以前,我认为它可以是0字节或者1000字节,它与语言规范没有任何关系。但是,在查看 C + + 17标准(expr.sizeof)之后,sizeof被定义为无论如何总是返回一个或更多。

派生最多的类的大小应大于零。

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

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


尽管如此,这个特别的措辞似乎已经从 C + + 20中删除,至少允许不占用空间的对象的 可能性。但是,在同一节中增加了以下案文:

当应用于类时,结果是该类 包括在数组中放置该类型对象所需的任何填充。对象中的字节数

由于数组需要能够区分元素,这意味着 sizeof必须返回至少一个元素,即使对象本身在技术上不占用空间。

所以,措辞不同,但总体效果相同。

标准规定所有大多数派生对象的 sizeof () > = 1:

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

引用 比雅尼·斯特劳斯特鲁普的 C + + 风格和技术常见问题解答,大小为非零的原因是“为了确保两个不同对象的地址将是不同的。”大小可以是1,因为对齐在这里并不重要,因为实际上没有什么可看的。

我认为它可能有助于链接到一个解释这个很好的答案。

空类的1字节分配依赖于编译器。编译器需要确保对象驻留在不同的内存位置,并且需要为对象分配非零内存大小。 听听这个话题的注释: < a href = “ http://listenvoice.com/listenVoiceNote.aspx? id = 27”rel = “ nofollow noReferrer”> http://listenvoice.com/listenvoicenote.aspx?id=27

即使编译器为空类分配非零大小,但当新类从空类派生时,它们也会进行优化。 在 ListenVoice 的 c + + 编程面试问题中听取关于空基优化的内容。

这是因为 这个指针,虽然指针是(整数)4字节但它引用 to a one memory location ( one Unit ) which is 1 byte.

类没有数据成员但有1个字节的原因是 this * 强烈的文字 * 必须存储在内存中,以便引用或指针可以指向该类的对象

This may help u :-) Http://bytes.com/topic/c/insights/660463-sizeof-empty-class-structure-1-a

空类或结构的大小为1

The reason this happens boils down to properly implementing the 标准,C + + 标准说的一件事是“没有对象” 应该在内存中具有与任何其他变量相同的地址”... 什么 是确保这一点最简单的方法吗? 确保所有类型都有一个 为了实现这一点,编译器添加了一个虚字节 到没有数据成员和虚拟的结构和类 函数的大小是1,而不是0 那么它们肯定有一个唯一的内存地址。

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

There is an exception: 0-length arrays

#include <iostream>


class CompletlyEmpty {
char NO_DATA[0];
};


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

空类-该类不包含任何内容。

任何不为空的类都将由其内存中的内容来表示。

现在空类在内存中是如何表示的? as it has no content no way to show its existance in memory, but class is present ,it is mandatory to show its presence in memory. 要在内存中显示空类存在,需要1个字节。

我认为这是因为1字节是最小的内存单元,可以用作占位符,它不能给零大小,因为它将不可能创建一个对象数组。.

and the thing you said "This was a little surprising to me since I was expecting it to be of the size of the machine word (32 bits or 4 bytes)." will be true for reference variable(macine words) of type empty(),not size of class itself(which is abstract data type),

我认为如果一个空类的大小为零,那就意味着它不存在。对于它(类)的存在,它需要至少有1个字节,因为这个字节是内存/引用地址。

我认为这个问题只是理论上的兴趣,实际上并不重要。

正如其他人已经指出的,从空类派生不会造成任何损害,因为这不会消耗基类部分的任何额外内存。

此外,如果一个类是空的(这意味着它理论上不需要任何每个实例的内存,也就是说它没有任何非静态数据成员或虚拟成员函数) ,那么它的所有成员函数都可以(也应该)定义为静态的。所以没有必要创建这个类的实例。

底线: 如果您发现自己正在编写一个空的类 X,那么只需将所有成员函数设置为静态。这样就不需要创建 X 对象,派生类也不会受到任何影响。

#include<iostream>
using namespace std;




class Empty { };
int main()
{
Empty* e1 = new Empty;
Empty* e2 = new Empty;


if (e1 == e2)
cout << "Alas same address of two objects" << endl;
else
cout << "Okay it's Fine to have different addresses" << endl;


return 0;
}

输出: 好的,可以有不同的地址

返回大小1可以确保两个对象的地址不相同。

确保两个不同的对象具有不同的地址是非零的。 不同的对象应该有不同的地址,所以空类的大小总是1字节。

对于空类的对象,编译器为唯一地址标识分配1个字节。因此,如果一个类有多个对象,它们可以有不同的唯一内存位置。假设,如果一个类没有任何大小,那么存储在内存位置上的内容是什么?这就是为什么当我们在 C + + 程序中创建一个空类的对象时,它需要一些内存来存储,可以保留的最小内存量是1字节。因此,如果我们创建一个空类的多个对象,每个对象将有一个唯一的地址。

在 C + + 代码示例下面,将始终为这两个对象提供为空类 EmptyClass 创建的唯一地址。

int main()
{
EmptyClass obj1;
EmptyClass obj2;
     

if (&obj1 == &obj2){
cout << "Both objects have same address" << endl;
}else{
cout << "Both objects have unique address" << endl;
}
return 0;
}