How does sizeof work in C++?

Hello,

I learned compiler doesn't memory allocation for class without an object.
When we declare an object compiler allocates memory for it.

So why in the following example size is not zero? I don't create any object and I expect to have 0 in size.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>
using namespace std;

class Base
{
public:
	void Print() {
		cout << "In Base..";
	}
	int a;
};

class emptyClass
{
};


int main() {

	Base b;
	emptyClass ec;

	cout << sizeof(Base) << endl; // 4  without create object 
	cout << sizeof(emptyClass) << endl; // 1  without create object 

	cout << sizeof(b) << endl; // 4
	cout << sizeof(ec) << endl; // 1

	return 0;
}
Last edited on
The size of an object (i.e. instance of a class) is fixed and known at compile-time. That's why sizeof works.

The same applies to structs, except when a "flexible array member" is used, as well as with arrays.

(note: when used with an array, sizeof returns its total size, in bytes)

You do not have to actually allocate an object to know how much memory an instance of a class would take!

sizeof(f) and sizeof(Foo), where f is a variable of class/struct Foo, are effectively the same.


sizeof operator

When applied to a class type, the result is the number of bytes occupied by a complete object of that class, including any additional padding required to place such object in an array. The number of bytes occupied by a potentially-overlapping subobject may be less than the size of that object.

The result of sizeof is always nonzero, even if applied to an empty class type.


See also:
https://www.stroustrup.com/bs_faq2.html#sizeof-empty
Last edited on
Thanks,

I read:
The memory space is allocated to the data members of a class only when an object of the class is declared, and not when the data members are declared inside the class.


So my main question is:

Why does sizeof(Base) 4?

I didn't create an instance of the Base class and expected the compiler doesn't allocate memory for Base.

Please see the following code:
1
2
cout << sizeof(Base) << endl; // 4  without create object 
	cout << sizeof(emptyClass) << endl; // 1  without create object 
Again, to the sizeof operator, it is totally irrelevant what you actually allocate, or not allocate.

The sizeof operator tells you the size of an object of the specified type, in bytes.

You do not have to actually allocate an object to know how much memory an instance of a class would take.

Your C++ compiler determines the size of an object from the class' definition – which is fixed at compile-time.

So, sizeof(Base) returns 4, because every instance (object) of type Base always is 4 bytes in size ;-)

sizeof(b) also returns 4, because b is of type Base, and because sizeof(Base) is 4.

Finally, if you wonder why the size of an "empty" class is not zero, please see the FAQ link I posted above!
Last edited on
kigar64551 wrote:
The size of an object (i.e. instance of a class) is fixed and known at compile-time. That's why sizeof works.

The same applies to structs, except when a "flexible array member" is used, as well as with arrays.


The size of those things are fixed and known too. The flexible array member just lets you get away with accessing elements beyond the declared size of the struct without directly invoking UB.
Yes, I know. It's just important to be aware that, when it comes to structs with "flexible array member", then sizeof() gives you the fixed size of the struct disregarding the "flexible" member. The actual size of the struct (memory block), as allocated by malloc() at runtime, can be (and usually is) larger than that.
Last edited on
That "flexible array member" is not in C++ Standard, is it? Lets leave such scary VLA's to C.


When compiler compiles code that must allocate memory for object, it must be able to generate the correct instructions -- how many bytes to allocate.

1
2
3
4
5
6
class Base
{
public:
	void Print();
	int a;
};

is a definition of a type named "Base". Compiler can calculate from that definition how many bytes to allocate for an object of type Base. The size is at least the sum of sizes of all members. Here is member of type int and compiler has size for it. The sizeof merely returns the result of that calculation.

Declaration of a member variable within class definition is not quite same as declaration of variable within function. Class definition is mere description of what could be.

1
2
3
4
5
6
7
8
9
struct Sample
{
  double x;
  double y;
};

int main() {
  int z;
}

The executable of program above is practically identical with code below because the program does not use any Sample objects.
1
2
3
int main() {
  int z;
}

The following program will allocate memory for one int, two double and perhaps some padding too:
1
2
3
4
5
6
7
8
9
10
struct Sample
{
  double x;
  double y;
};

int main() {
  int z;
  Sample w;
}


This translation unit does not need to know the size of type Sample, because it only has pointers:
1
2
3
4
5
6
7
struct Sample;
void func( Sample* );

int main() {
  Sample* w = nullptr;
  func( w );
}

Last edited on
It has been proposed but it looks like there was no consensus to spend time on it.

https://github.com/cplusplus/papers/issues/27
Last edited on
Topic archived. No new replies allowed.