121

I was wondering what could be the size of an object of an empty class. It surely could not be 0 bytes since it should be possible to reference and point to it like any other object. But, how big is such an object?

I used this small program:

#include <iostream>
using namespace std;

class Empty {};

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

The output I got on both Visual C++ and Cygwin-g++ compilers was 1 byte! 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).

Can anyone explain why the size of 1 byte? Why not 4 bytes? Is this dependent on compiler or the machine too? Also, can someone give a more cogent reason for why an empty class object will not be of size 0 bytes?

Ashwin Nanjappa
  • 76,204
  • 83
  • 211
  • 292
  • I see no reason why it could not be zero. But by giving it a size others things are easier in the compiler. If you have an array of these things then each element needs a unique address. A size of 1 makes this easy. – Martin York Mar 07 '09 at 10:32
  • 2
    It can be zero-sized if it is a base class subobject. – Johannes Schaub - litb Jul 21 '12 at 11:24

17 Answers17

143

Quoting Bjarne Stroustrup's C++ Style and Technique FAQ, the reason the size is non-zero is "To ensure that the addresses of two different objects will be different." And the size can be 1 because alignment doesn't matter here, as there is nothing to actually look at.

Lena Schimmel
  • 7,203
  • 5
  • 43
  • 58
Sol
  • 2,175
  • 1
  • 13
  • 9
  • 59
    Bah, what the heck would he know about C++? :-) – paxdiablo Mar 17 '09 at 04:37
  • Does the need to "ensure that the addresses of two different objects will be different" have something to do with C++? I mean why was the need not felt for C? – Lazer May 16 '10 at 05:21
  • 21
    @Lazer, because there are no empty structs in C. – aib Nov 04 '10 at 10:16
  • 7
    @nurabha The this pointer points *to* the object. It's not stored in the object. If, however, there are virtual functions, the object contains a pointer to the vtable. – tbleher Sep 19 '13 at 17:03
  • @tbleher: Right. So in case there are virtual functions in empty class then its size should size of pointer to vtable ...4 bytes or 8 bytes ? – nurabha Sep 19 '13 at 18:29
  • @nurabha: Depends on the pointer size of the architecture (so 4bytes on x86, 8bytes on 64bit architectures). Note also that the C++ standard doesn't mandate use of a vtable pointer, but all common implementations use one. – tbleher Sep 20 '13 at 08:18
  • @sol: as you said "To ensure that the addresses of two different objects will be different". So we know to store address we need a pointer variable and hence I think that since a pointer is required here the size of the empty class should be sizeof(ptr). – Krishna Oza Jan 29 '14 at 04:09
  • 4
    @krish_oza: you think wrong. When you allocate a variable on stack, it cannot occupy zero bytes (because different variables need different addresses), hence the size 1 minimum. After that, it is up to the compiler. Similarly with `new`; when the space is allocated, another allocation must have a different address. And so on. There isn't necessarily any pointer involved in the empty class; there may be pointers to the variables (or references, or local/stack allocations), but they're not zero size and they are not necessarily pointer size. – Jonathan Leffler Feb 28 '14 at 20:35
  • I wonder why this is not the case for C struct? If C can avoid address clash, why not C++? – Barun Aug 14 '14 at 17:11
  • About empty base class optimization https://isocpp.org/wiki/faq/classes-and-objects : empty base class optimization” is no longer an optional optimization but a mandatory requirement on class layout as of C++11 – Konstantin Burlachenko Jul 30 '15 at 11:25
  • @sol why address of two object have to be different? – VINOTH ENERGETIC Oct 27 '16 at 16:50
  • What about `sizeof(Empty)`. It's also 1, even it's nothing to do with any instances. I think the size of object with no data (zero-sized array, empty class, class with only static members, `void`) should be zero, because it is the real size of the object. Yes, the expression `sizeof(void)` is 1. What is that 1 you found in the void? If you create array of 500 objects of size 0, then the `sizeof` this array should be 0 too. You do not need to diferentiate these objects, because there are nothing to diferentiate. So `obj[1]` is so empty as `obj[1]`. It's a void. –  Aug 20 '17 at 06:44
33

The standard states that all most derived objects have sizeof() >= 1:

Unless it is a bit-field (class.bit), a most derived object shall have a non-zero size and shall occupy one or more bytes of storage. Base class sub-objects may have zero size. ISO/IEC FDIS 14882:1998(E) intro.object

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
TrayMan
  • 7,180
  • 3
  • 24
  • 33
  • 1
    I find that hard to believe. The standard goes out of its way to make sure implementations have a free hand to do a good job of optimization tying the hands of the implementer like that does not sound like the kind of the thing the standard normally does (I could be wrong) – Martin York Mar 07 '09 at 10:35
  • 4
    @eSKay - This is required so that different objects get different addresses. You could not have a map of pointers to objects, for example, if different instances had the same address. – Brian Neal May 16 '10 at 17:34
19

That's really an implementation detail. Once long ago, I thought it could be zero bytes or a thousand bytes, that it has no bearing on the language specification. But, after looking at the C++17 standard (expr.sizeof), sizeof is defined as always returning one or greater, no matter what.

The size of a most derived class shall be greater than zero.

This is required for, among other things, allowing you to handle arrays of objects and pointers to them. If your elements were allowed to be zero-sized then &(array[0]) would be identical to &(array[42]), which is going to cause all sorts of havoc to your processing loops.

The reason why it may not be a machine word is that there are no elements within it that actually require it to be aligned on a word boundary (such as an integer). For example, if you place char x; int y; inside the class, my GCC clocks it at eight bytes (since the second int must be aligned in that implementation).


Having said that, that particular wording appears to have been removed from C++20, allowing for at least the possibility of objects that can take up no space. However, the following text has been added to that same section:

When applied to a class, the result is the number of bytes in an object of that class including any padding required for placing objects of that type in an array.

Since arrays need to be able to distinguish between elements, that would mean sizeof would have to return at least one, even if the object itself technically took up no space.

So, different wording, but the same overall effect.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • The reason for the "not zero" is that different objects should have different addresses. Imagine an array of zero-size objects. How would you index it? In some cases, the compiler is allowed to optimize this away though (the empty base class optmization) – jalf Mar 07 '09 at 11:07
  • @jalf: "How would you index it?" The same way I would do in C (for an array of struct objects, for example)?? – Lazer May 16 '10 at 05:24
  • 1
    @eSKay - You couldn't if they had 0 size. They'd all be at element 0. – Brian Neal May 16 '10 at 17:35
  • 2
    @BrianNeal which is no problem, since they have no state to differentiate themselves. The problems only arrive when you consider pointers. – danielschemmel May 15 '13 at 10:16
  • 2
    Or taking the size of said array to compute its length. – danielschemmel May 15 '13 at 10:18
  • Consider if you wanted to loop across said array, you have a begin pointer, and a length, N, so you compute the "end" pointer with begin+N. This works perfectly as long as objects have non-zero size. However, if they have zero size, begin==end, and you'll cut your loop short. – Cort Ammon May 14 '15 at 23:36
  • Just because they don't have any members doesn't mean they don't have state. State could be stored elsewhere - if the address is used as an unique token to access an external system, or state could be in a hash map keyed by address. – Ben Jan 27 '17 at 18:17
5

Even though its not required to assign any memory for an empty class, but in order to make objects of empty classes, compiler assigns the minimum memory that can be assigned, which is 1 byte. This way compiler can distinguish two objects of the same empty class uniquely, and will able to assign the address of the object to a pointer of the empty class type.

lalatendu
  • 51
  • 1
  • 1
4

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';
}
Konstantin Nikitin
  • 2,256
  • 1
  • 17
  • 12
  • Why nobody has commented this answer? It seems very curious for me. – ABu Dec 31 '12 at 10:50
  • If you create two "CompletelyEmpty" objects ('a' and 'b' for example), sizeof says they are 0 bytes long, but its addresses are diferents ('&a == &b' evaluates false) . And this should be impossible... (using g++ 4.7.2). – ABu Dec 31 '12 at 10:55
  • 1
    But if you create an array of this objects, say, `c`, `&c[M] == &c[N]` for every `M` and `N` (clang++ 4.1). – Konstantin Nikitin Jan 01 '13 at 15:28
  • 6
    C and C++ doesn't allow zero-length arrays. Your compiler could, but it's incorrect. – Konrad Borowski Apr 14 '13 at 12:44
  • yes, the Class size itself is zero, but an instance of this class is still 1 byte. – ZeR0 Sep 05 '13 at 13:16
  • @KonstantinNikitin nice point, I have tested the above code on "gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3" But I am now confused how is it possible to have same address to two different objects. – Krishna Oza Jan 29 '14 at 05:11
  • The size of `class F { int f[0]; };` is 1 on Visual C++ 2010. – TT_ stands with Russia Jan 29 '14 at 18:49
  • 1
    Some compilers still give a non-zero size to classes like `CompletlyEmpty` [sic]. And, in fact, it appears a zero-length array member is a non-standard extension. So I don't think this is an interesting example. – Adrian McCarthy Nov 14 '17 at 19:29
  • 3
    That is not actually valid C++. From the C++20 standard for declaring arrays, `[dcl.array]`: "If the constant-expression is present, it shall be a converted constant expression of type `std::size_t` and ***its value shall be greater than zero***." – paxdiablo Feb 14 '21 at 23:54
4

I think it might be helpful to link to an answer explaining this good too. It is about boost::compressed_pair by Logan Capaldo.

Community
  • 1
  • 1
Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
3

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

The sizeof an empty class or structure is 1

The reason this happens boils down to properly implementing the standard, one of the things the C++ standard says is that "no object shall have the same address in memory as any other variable".... What is the easiest way to ensure this? Make sure that all types have a non-zero size. In order to achieve this the compiler adds a dummy byte to structures and classes that have no data members and no virtual functions so that they have a size of 1 rather than a size of 0 and then they are guaranteed to have a unique memory address.

Peter O.
  • 32,158
  • 14
  • 82
  • 96
2

Allocation of 1 byte for an empty class is compiler dependent. Compilers need to make sure objects reside in different memory locations and they need to allocate non zero memory size to an object. Listen to notes on this topic here: http://listenvoice.com/listenVoiceNote.aspx?id=27

Even though compilers allocates non zero size to an empty class they also do optimizations when new classes are derived from empty classes. Listen about empty base optimization on ListenVoice's c++ programming interview questions.

user332764
  • 21
  • 1
2

the reason for class with no data members but having size 1 byte is that the this*strong text* must be stored in memory so that a reference or pointer can point to the object of that class

Ramiz
  • 21
  • 1
0

empty class -that class does not contain any content.

any class which is not empty will be represented by its content in memory.

now how empty class will be represented in memory? 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. To show empty class presence in memory 1 byte is required.

Ganesh
  • 1
0

I think it is so because as 1 byte is the smallest memory unit that can be used as a placeholder, and it cannot give zero size as it will not be possible to create an array of objects ..

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),

lazarus
  • 677
  • 1
  • 13
  • 27
0

I think this question is only of theoretical interest but doesn't matter in practice.

As already pointed out by others, deriving from an empty class doesn't do any harm, as this will not consume any extra memory for the base class portion.

Moreover, if a class is empty (meaning that it - theoretically - doesn't need any per-instance memory, i.e. it doesn't have any non-static data members or virtual member functions) then all its member functions can just as well (and should) be defined as static. So there is no need to ever create an instance of this class.

Bottom line: If you find yourself writing an empty class X then just make all member functions static. You then won't need to create X objects, and derived classes will not be affected in any way.

kidfisto
  • 41
  • 1
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;
    }

Output: Okay it's Fine to have different addresses

Returning size 1 ensures that the two objects will not have the same address.

Sandeep_black
  • 1,352
  • 17
  • 18
0

It is nonzero to ensure that the two different objects will have different addresses. Different objects should have different addresses, so the size of an empty class is always 1 byte.

0

To an object of an empty class, 1 byte is allocated by the compiler for unique address identification. So, if a class have multiple objects they can have different unique memory location. Suppose, if a class does not have any size, what would be stored on the memory location? That’s the reason when we create an object of an empty class in the C++ program, it needs some memory to get stored, and the minimum amount of memory that can be reserved is 1 byte. So, if we create multiple objects of an empty class, every object will have a unique address.

Below the C++ code example, will always provide a unique address for both objects, created for the empty class 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;
}
-2

I think that if the size of an empty class is zero it means that it does not exist. For it (class) to exist, it requires to have at least 1 byte, since this byte is the memory/reference address.

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
Honey
  • 1
-3

It is because of this pointer , although pointer is (integer) of 4 byte but it refer to a one memory location ( one Unit ) which is 1 byte.

  • 7
    Sorry, but this is nonsense. – jogojapan Feb 25 '13 at 13:20
  • @Narayan das khatri : first the type of pointer depends on the data type its not int always and second the size of the pointer depends on machine and compiler on 32 bit machines it's 4 byte and for 64 bit machines it's 8 byte. – Krishna Oza Jan 29 '14 at 05:16