Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

sizeof class with int , function, virtual function in C++?

This is an online C++ test question, which has been done.

#include<iostream>
using namespace std; 
class A
{

};
class B
{
int i; 
}; 

class C
{
void foo();
};
class D
{
virtual void foo();
};

class E
{
int i ; 
    virtual void foo();
};
class F
{
int i; 
    void foo();
};
class G
{
    void foo();
    int i;
    void foo1();
};

class H
{
    int i ;
    virtual void foo();
    virtual void foo1();
};
int main()
{
cout <<"sizeof(class A) : " << sizeof(A) << endl ;
cout <<"sizeof(class B) adding the member int i : " << sizeof(B) << endl ;
cout <<"sizeof(class C) adding the member void foo() : " << sizeof(C) << endl ;
cout <<"sizeof(class D) after making foo virtual : " << sizeof(D) << endl ;
cout <<"sizeof(class E) after adding foo virtual , int : " << sizeof(E) << endl ;
cout <<"sizeof(class F) after adding foo  , int : " << sizeof(F) << endl ;
cout <<"sizeof(class G) after adding foo  , int : " << sizeof(G) << endl ;
G g;
cout <<"sizeof(class G) after adding foo  , int : " << sizeof(g) << endl ;
cout <<"sizeof(class H) after adding int 2 virtual " << sizeof(H) << endl ;
return 0; 
}

output:

sizeof(class A) : 1
sizeof(class B) adding the member int i : 4
sizeof(class C) adding the member void foo() : 1
sizeof(class D) after making foo virtual : 8
sizeof(class E) after adding foo virtual , int : 16
sizeof(class F) after adding foo  , int : 4
sizeof(class G) after adding foo   , unsigned int : 4
sizeof(class g) after adding foo  , unsigned int : 4
sizeof(class H) after adding int 2 virtual 16

My questions:

Why siszeof(A) is 1 and sizeof(C) is 1 too ?

Why siszeof(H) is 16 but sizeof(G) is 4 ?

Why siszeof(E) is 16 but sizeof(F) is 4 ?

Why siszeof(D) is 8 but sizeof(E) is 16 ?

My guess:

A virtual function is a pointer with 8 bytes. But, I do not know why E size is 16 ? Adding a function to an empty class does not change its size ?

Any help is appreciated.

thanks

like image 627
user1002288 Avatar asked Feb 24 '12 22:02

user1002288


People also ask

What is the size of class with virtual function?

A virtual function is a pointer with 8 bytes.

How virtual function affects on size of object?

The use of virtual functions increases the size of an object, typically by the size of a pointer to the vtable. This may be an issue if you wish to create a small object that requires a very large number of instances.

What is the size in bytes of an empty class with a virtual function?

Size of an empty class is not zero. It is 1 byte generally. It is nonzero to ensure that the two different objects will have different addresses.


2 Answers

First off, a virtual function is not a pointer with 8 bytes. In C++ nothing but sizeof(char) is guaranteed to be any number of bytes.

Second, only the first virtual function in a class increases its size (compiler-dependent, but on most - if not all - it's like this). All subsequent methods do not. Non-virtual functions do not affect the class's size.

This happens because a class instance doesn't hold pointers to methods themselves, but to a virtual function table, which is one per class.

So if you had:

class A
{
   virtual void foo();
}

and

class B
{
   virtual void goo();
   virtual void test();
   static void m();
   void x();
}

you would have sizeof(A) == sizeof(B).

And now:

Why siszeof(A) is 1 and sizeof(C) is 1 too ?

A and C have size 1 just because it's not allowed for a class to be of size 0. The functions have nothing to do with it. It's just a dummy byte.

Why siszeof(H) is 16 but sizeof(G) is 4 ?

G has only one member that accounts for memory - the int. And on your platform, sizeof(int) == 4. H, besides the int, also has a pointer to the vftable (virtual function table, see above). The size of this, size of int and allignment are compiler specific.

Why siszeof(E) is 16 but sizeof(F) is 4 ?

Explained above - non virtual methods don't take up memory in the class.

Why siszeof(D) is 8 but sizeof(E) is 16 ?

D only contains the vftable pointer which is apparently 8 bytes on your platform. E also has an int, and the vftable is aligned to 8 bytes. So it's something like:

class E

4 bytes for int |  4 padding bytes  |  8 bytes for vftable pointer  | 
| x | x | x | x |    |    |    |    | v | v | v | v | v | v | v | v |
like image 135
Luchian Grigore Avatar answered Oct 13 '22 08:10

Luchian Grigore


Why siszeof(A) is 1 and sizeof(C) is 1 too ?

The function in C is not virtual, so the class doesn't need a vtable pointer, so it needs no more storage than A. Neither A nor C need any storage at all, but because language requires that different instances of the same class have different pointers, they can't have a size of zero - so the compiler makes them as small as it can, i.e. 1 byte.

Why siszeof(H) is 16 but sizeof(G) is 4 ?

G has no virtual functions, so all it needs to store is the int, which on your compiler and architecture is 4 bytes.

H has virtual functions, so the class needs to contain an int and a vtable pointer. All widely used compilers store the vtable pointer at the start of the class, so the layout is {vptr, int}, which is 8+4=12 bytes if you're on a 64 bit host.

However, the compiler is free to pad this out to 16 bytes so that if multiple instances of H are allocated in an array then all of them will be word-aligned. This is important because there are significant performance implications for accessing a pointer (i.e. the vtable pointer here) if it is not word-aligned.

Why siszeof(E) is 16 but sizeof(F) is 4 ?

E has virtual functions, so needs a vtable ptr, so its layout is just like H's. F has no virtual functions, it only has an int, so its layout is just like G's. so the answer's the same as for G and H.

The ordering of the members/functions just doesn't matter here because there's only one member variable and the vtable ptr always goes first if there is one.

Why siszeof(D) is 8 but sizeof(E) is 16 ?

D has no member variables, but it has a virtual function, so it needs a vtable pointer. The vtable pointer is the only thing it needs, so its size is sizeof(void*), which is 8 bytes. E needs the same as D, plus 4 bytes for an integer, and the compiler rounds it up to 16 bytes for alignment.

like image 33
je4d Avatar answered Oct 13 '22 09:10

je4d