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


111

我想知道一个空类的对象大小是多少。它肯定不能为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字节)。

谁能解释为什么 1个字节的大小?为什么不是 4个字节?这也取决于编译器或计算机吗?另外,有人可以给出更确切的理由说明为什么空的类对象的大小为0字节吗?


我看不出为什么它不能为零。但是通过给它一个大小,其他东西在编译器中会更容易。如果您拥有这些东西的数组,那么每个元素都需要一个唯一的地址。大小为1可使此操作变得容易。
马丁·约克2009年

2
如果它是基类的子对象,则其大小可以为零。
Johannes Schaub-litb 2012年

Answers:


129

引用Bjarne Stroustrup的C ++样式和技术常见问题解答,大小不为零的原因是“确保两个不同对象的地址将不同”。大小可以为1,因为这里的对齐方式无关紧要,因为实际上没有什么要看的。


55
Bah,他对C ++有什么了解?:-)
paxdiablo

18
@Lazer,因为在C中没有空结构
。– aib

7
@nurabha的该指针指向该对象。它没有存储在对象中。但是,如果存在虚函数,则该对象包含指向vtable的指针。
tbleher

4
@krish_oza:你认为错了。在堆栈上分配变量时,它不能占用零字节(因为不同的变量需要不同的地址),因此大小最小为1。之后,由编译器决定。与new; 类似; 当分配空间时,另一个分配必须具有不同的地址。等等。空类中不一定涉及任何指针。可能存在指向变量(或引用或本地/堆栈分配)的指针,但它们的大小不是零,并且不一定是指针大小。
乔纳森·莱夫勒

3
@Destructor,不是很聪明,但是我确实知道什么是笑脸:-)您可能希望以此来重新阅读评论,并意识到这是幽默。
paxdiablo '16

30

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

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


1
我觉得很难相信。该标准将竭尽所能,以确保实现方案有空余的手可以很好地完成优化工作,并紧紧束缚在实现者的手中,这听起来好像不是标准通常所做的那种事情(我可能是错的)
马丁·约克2009年

4
@eSKay-这是必需的,以便不同的对象获得不同的地址。例如,如果不同的实例具有相同的地址,则无法获得指向对象的指针的映射。
布莱恩·尼尔

14

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

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

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

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


“非零”的原因是不同的对象应具有不同的地址。想象一个零尺寸对象的数组。您将如何编制索引?在某些情况下,允许编译器对此进行优化(空基类优化)
杰夫

@jalf:“您将如何为其编制索引?” 我将在C中执行相同的方式(例如,对于结构对象数组)?
拉泽尔

1
@eSKay-如果大小为0,则无法显示。他们全是在元素0
布赖恩·尼尔

1
@BrianNeal没问题,因为他们没有区别自己的状态。仅当您考虑指针时问题才出现。
gha.st

2
或者采用所述阵列的大小来计算其长度。
gha.st 2013年

6

有一个例外:0长度数组

#include <iostream>

class CompletlyEmpty {
  char NO_DATA[0];
};

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

为什么没人评论这个答案?对我来说似乎很好奇。
Peregring-lk 2012

如果创建两个“ CompletelyEmpty”对象(例如,“ a”和“ b”),则sizeof表示它们的长度为0个字节,但其地址不同(“&a ==&b”的值为false)。这应该是不可能的...(使用g ++ 4.7.2)。
Peregring-lk 2012

1
但是,如果您为每个对象创建一个数组c&c[M] == &c[N]对每个M和说N(clang ++ 4.1)。
康斯坦丁·尼基汀

5
C和C ++不允许零长度数组。您的编译器可以,但是不正确。
Konrad Borowski13年

是的,类大小本身为零,但此类的实例仍为1个字节。
ZeR0

5

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



3

这可能对您有帮助:-) http://bytes.com/topic/c/insights/660463-sizeof-empty-class-structure-1-a

空类或结构的大小为1

发生这种情况的原因归结为正确实施该标准,C ++标准说的一件事是“任何对象在内存中都不得与任何其他变量具有相同的地址”。确保所有类型的大小都为非零。为了实现这一点,编译器向没有数据成员和虚拟函数的结构和类中添加了一个虚拟字节,以使它们的大小为1,而不是0,然后保证它们具有唯一的内存地址。


2

空类的1字节分配取决于编译器。编译器需要确保对象位于不同的内存位置,并且需要为对象分配非零的内存大小。在此处收听有关此主题的注释: http //listenvoice.com/listenVoiceNote.aspx?id=27

即使编译器将非零大小分配给空类,当从空类派生新类时,它们也会进行优化。听听关于ListenVoice的C ++编程面试问题的空基础优化。


2

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


0

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

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

现在如何在内存中表示空类?由于它没有内容,无法显示其在内存中的存在,但是类存在,因此必须显示其在内存中的存在。要显示内存中存在空类,需要1个字节。


0

我认为是这样,因为1字节是可以用作占位符的最小存储单元,并且不能给出零大小,因为将不可能创建对象数组。

您说的话:“这让我感到有些惊讶,因为我希望它具有机器字的大小(32位或4字节)。” 对于类型为empty()的引用变量(机器单词),而不是类本身的大小(抽象数据类型),将为true,


0

我认为这个问题只具有理论意义,而在实践中并不重要。

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

此外,如果一个类为空(从理论上讲,它不需要任何实例存储,即它没有任何非静态数据成员或虚拟成员函数),则其所有成员函数也可以(并且应该)定义为静态。因此,无需创建此类的实例。

底线:如果您发现自己写了一个空的类X,则只需将所有成员函数设为静态即可。然后,您将不需要创建X对象,并且派生类将不会受到任何影响。


0
#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可以确保两个对象的地址不同。


0

确保两个不同的对象具有不同的地址是非零的。不同的对象应具有不同的地址,因此空类的大小始终为1个字节。


-2

我认为,如果一个空类的大小为零,则意味着它不存在。要使它(类)存在,它必须至少有1个字节,因为该字节是内存/引用地址。


-3

由于指针,尽管指针是4字节的(整数),但它指向的是1字节的一个存储位置(一个Unit)。


5
抱歉,这是胡扯。
jogojapan

@Narayan das khatri:首先,指针的类型取决于数据类型,而不是总是int;第二,指针的大小取决于计算机和编译器;在32位计算机上,指针是4字节;在64位计算机上,指针是8字节。
克里希纳(Krishna Oza)2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.