Login or Sign up Help | Site Map
Connecting Tech Pros Worldwide

The sizeof an empty class or structure is 1

Written by Banfa, June 11th, 2007
I thought I would write a little article about this because it is regularly asked as a question in the Forums.

Firstly this is a C++ issue, it is strictly against the rules of C to create a class with no members. This makes sense because the only real use for a structure or class with no data members and virtual functions is as the base from which to derive other classes and structures or as a container for non-virtual methods.

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". There is a very good reason for this, take an array of type T then subtracting the pointer to 1 entry in the array from another should give the difference in indexes

Code: ( text )
  1. T array[5];
  2.  
  3. int diff = &array[3] - &array[2];
  4.  
  5. // diff = 1


This is actually pointer arithmetic, we have taken 2 pointers and found their difference. The compiler performs this calculation using a formula equivalent to this

diff = ((char *)&array[3] - (char *)&array[2]) / sizeof T;

This is just an example, but this type of calculation reliant on the sizeof T occurs in all sorts of pointer arithmetic.

If objects were allowed to have the same address because their type was 0 sized then this calculation would not be possible because

Code: ( text )
  1. &array[3] - &array[2] = &array[3] - &array[1]
  2.                       = &array[3] - &array[1]
  3.                       = &array[3] - &array[0]
  4.                       = 0


It is not possible to distinguish the different objects in pointer arithmetic.

Additionally there is the problem that the compiler had to divided by sizeof T, which would be a divide by zero error, although this could be coded round.

Allowing objects to have the same memory address would result in the need to implement some rather complex code to handle pointer arithmetic on them.

So objects must not have the same memory address, that is they must be individually addressable. 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.

3 Comments Posted ( Post your comment )
weaknessforcats / December 10th, 2007 04:21 PM
A class (or struct) can have member functions without using any data members. Unless you can create an object of this class, you can't call the methods. For this reason, a class (or struct) that has no data members is created with a sizeof 1 byte.

This also allows you to define a pointer to an object of that class. You can't define a pointer of you cannot acquire the address of an object of the pointer type. One byte is the smallest addressable memory unit. The only time in C++ when you cannot create an object of the class is when it contains (or has inherited) a pure virtual function.

Code: ( text )
  1. class MyClass
  2. {
  3.     public:
  4.        void AMethod() {cout << "Hello" << endl;}
  5. };
  6. int main()
  7. {
  8.     MyClass obj;
  9.     MyClass* ptr = &obj;
  10.     obj.AMethod();
  11.     ptr->AMethod();
  12.     cout << sizeof(obj) << endl;    //displays 1
  13. }


When a class contains no data variables but does have at least one virtual function, the object is created containing the address of the virtual funciton table (VTBL) as part of the object. Because of this, the size of the object will now be 4.

Code: ( text )
  1. class MyClass
  2. {
  3.     public:
  4.        virtual void AMethod() {cout << "Hello" << endl;}
  5. };
  6. int main()
  7. {
  8.     MyClass obj;
  9.     MyClass* ptr = &obj;
  10.     obj.AMethod();
  11.     ptr->AMethod();
  12.     cout << sizeof(obj) << endl;    //displays 4
  13. }
Peterwkc / March 2nd, 2008 02:03 AM
I don't understand about the statement.

Its space overhead is one pointer in each object of a class with a virtual function plus one vtbl for each such class.

Please clear my doubt.

Thanks.
weaknessforcats / March 4th, 2008 05:49 PM
I think you almost understand this.

There is one VTBL for all objects of a class with virtual functions.

Each object of the class has a pointer to that VTBL. Therefore, the overhead in each object is one pointer.

Stats:
Views: 3330
Comments: 3