How Is the Size of a C++ Class Determined

How is the size of a C++ class determined?

For POD (plain old data), the rules are typically:

  • Each member in the structure has some size s and some alignment requirement a.
  • The compiler starts with a size S set to zero and an alignment requirement A set to one (byte).
  • The compiler processes each member in the structure in order:
  1. Consider the member’s alignment requirement a. If S is not currently a multiple of a, then add just enough bytes to S so that it is a multiple of a. This determines where the member will go; it will go at offset S from the beginning of the structure (for the current value of S).
  2. Set A to the least common multiple1 of A and a.
  3. Add s to S, to set aside space for the member.
  • When the above process is done for each member, consider the structure’s alignment requirement A. If S is not currently a multiple of A, then add just enough to S so that it is a multiple of A.

The size of the structure is the value of S when the above is done.

Additionally:

  • If any member is an array, its size is the number of elements multiplied by the size of each element, and its alignment requirement is the alignment requirement of an element.
  • If any member is a structure, its size and alignment requirement are calculated as above.
  • If any member is a union, its size is the size of its largest member plus just enough to make it a multiple of the least common multiple1 of the alignments of all the members.

Consider your TestClass3:

  • S starts at 0 and A starts at 1.
  • char buf[8] requires 8 bytes and alignment 1, so S is increased by 8 to 8, and A remains 1.
  • __m128i vect requires 16 bytes and alignment 16. First, S must be increased to 16 to give the correct alignment. Then A must be increased to 16. Then S must be increased by 16 to make space for vect, so S is now 32.
  • char buf2[8] requires 8 bytes and alignment 1, so S is increased by 8 to 24, and A remains 16.
  • At the end, S is 24, which is not a multiple of A (16), so S must be increased by 8 to 32.

So the size of TestClass3 is 32 bytes.

For elementary types (int, double, et cetera), the alignment requirements are implementation-defined and are usually largely determined by the hardware. On many processors, it is faster to load and store data when it has a certain alignment (usually when its address in memory is a multiple of its size). Beyond this, the rules above follow largely from logic; they put each member where it must be to satisfy alignment requirements without using more space than necessary.

Footnote

1 I have worded this for a general case as using the least common multiple of alignment requirements. However, since alignment requirements are always powers of two, the least common multiple of any set of alignment requirements is the largest of them.

How do you determine the size of an object in C++?

To a first order approximation, the size of an object is the sum of the sizes of its constituent data members. You can be sure it will never be smaller than this.

More precisely, the compiler is entitled to insert padding space between data members to ensure that each data member meets the alignment requirements of the platform. Some platforms are very strict about alignment, while others (x86) are more forgiving, but will perform significantly better with proper alignment. So, even the compiler optimization setting can affect the object size.

Inheritance and virtual functions add an additional complication. As others have said, the member functions of your class themselves do not take up "per object" space, but the existence of virtual functions in that class's interface generally implies the existence of a virtual table, essentially a lookup table of function pointers used to dynamically resolve the proper function implementation to call at runtime. The virtual table (vtbl) is accessed generally via a pointer stored in each object.

Derived class objects also include all data members of their base classes.

Finally, access specifiers (public, private, protected) grant the compiler certain leeway with packing of data members.

The short answer is that sizeof(myObj) or sizeof(MyClass) will always tell you the proper size of an object, but its result is not always easy to predict.

How to find the size of a class in C#

Short answer:

You dont.

Long answer:

You can only do that if you type has a fixed layout and has no managed members. Structs are fixed by default. Classes can attributed to have a fixed layout.

(I am not showing how, as you really do not need it. It is only important when doing interop.)

Size of A Class (object) in .NET

The size of a class instance is determined by:

  • The amount of data actually stored in the instance
  • The padding needed between the values
  • Some extra internal data used by the memory management

So, typically a class containing a string property needs (on a 32 bit system):

  • 8 bytes for internal data
  • 4 bytes for the string reference
  • 4 bytes of unused space (to get to the minimum 16 bytes that the memory manager can handle)

And typically a class containing an integer property needs:

  • 8 bytes for internal data
  • 4 bytes for the integer value
  • 4 bytes of unused space (to get to the minimum 16 bytes that the memory manager can handle)

As you see, the string and integer properties take up the same space in the class, so in your first example they will use the same amount of memory.

The value of the string property is of course a different matter, as it might point to a string object on the heap, but that is a separate object and not part of the class pointing to it.

For more complicated classes, padding comes into play. A class containing a boolean and a string property would for example use:

  • 8 bytes for internal data
  • 1 byte for the boolean value
  • 3 bytes of padding to get on an even 4-byte boundary
  • 4 bytes for the string reference

Note that these are examples of memory layouts for classes. The exact layout varies depending on the version of the framework, the implementation of the CLR, and whether it's a 32-bit or 64-bit application. As a program can be run on either a 32-bit or 64-bit system, the memory layout is not even known to the compiler, it's decided when the code is JIT:ed before execution.

Determining size of a polymorphic C++ class

If you know the set of possible types, you can use RTTI to find out the dynamic type by doing dynamic_cast. If you don't, the only way is through a virtual function.

How are the number of blocks for different classes in classful addressing determined in IPv4?

Keep in mind: you have 32 bits overall.

Class A uses one bit of those 32; so 31 are left. And guess what ... 2^7 and 2^24 results in ... 31 bits left for block data.

Classes D and E ... both using four bits; so 28 bits are left.
2^28 is ... surprise 268.435.456

Now just go and check how many bits are left for the other classes!

The thing is: those first bits are mutually exclusive.

When the 32 bits start with 0, you know: class A; and so on.

How does the c++ sizeof operator calculate size?

First, realise that functions that are not virtual have no effect on the size of a class.

The size of an instance of any class is at least 1 byte, even if the class is empty, so that different objects will have different addresses.

Adding a char ensures that different objects will have different addresses, so the compiler doesn't artificially add one to the size. The size is then sizeof(char) = 1.

Then you add an int, which (probably) adds 4 bytes on your platform. The compiler then decides to pad the class so it will be aligned for performance/CPU-requirements reasons, and adds 3 empty bytes so that the size is now 1 + 3 + 4 = 8. It probably adds the padding before the int member so that it will be aligned on a 4 byte boundary, but it's not required to unless your CPU requires it.

You can read about padding on the Wikipedia page.



Related Topics



Leave a reply



Submit