KoblentsBlog Photography
Contact About
Ches
Sizeof a class
To follow up on my previous post, here are some more cool things I learned about sizeof and classes in C++. I've been doing a lot of fun stuff with serializing and de-serializing classes with c-style casts to and from byte pointers, because it works fantastically well and very quickly and lends itself well to storage. Of course there are safer ways to do it, but that's the beauty of the things I'm doing - overhead is cut out whenever possible. So, fun learnings. A small overview first, and the rest after the jump.
Let's use well-recognizable types, defined in
<stdint.h>
. (See my previous article about sizes.) Let's assume we're on a 32-bit system and pointers are 32 bits in size.
1234567
class Foo {
	public:
		int8_t		a_byte;
		int16_t		a_short;
		uint32_t	a_uint;
		uintptr_t	a_ptr;
};

What do we get from
sizeof(Foo)
? It's fairly simple, by inspection, to count the bytes: 1 + 2 + 4 + 4 (because we assumed 32-bit system, 32-bit pointers) = 11 B. But now let's check out the more interesting cases after the jump.
123456789
class Foo {
	public:
		int8_t		a_byte;
		int16_t		a_short;
		uint32_t	a_uint;
		uintptr_t	a_ptr;
	public:					// not necessary, just for easy reading
		static ui32_t	a_static_uint;
};

We've added a static member variable, yet
sizeof(Foo) == 11
. Why? Simply put, a static variable in this context doesn't belong to any instance of the class, and sizeof measures the size of an instance. The variable is more of a global, stored globally, with class scope. The terminology here may be imprecise (or wrong) but I think the meaning is clear: no instance owns the static member variable, therefore it doesn't count for its size.
How about an empty class?
12
class Foo {
};

Looks like zero.
sizeof(Foo) == 1
. Hum! Apparently, the minimum size for a class is 1 byte, since we want to make sure that different instances of the class are allocated a non-zero size, so that they are then given different addresses. It's easy to see that if the class had a zero size, it could be given the same address as something else -- if malloc (or new) allocates linearly, by giving an address to use then moving the pointer to the next available address, a zero-size allocation wouldn't move the pointer. Oops!
How about an inherited class?
12345678
class Foo {
	public:
		uint32_t	a_uint;
};
class Bar : public Foo {
	public:
		uint32_t	another_uint;
};

As you might guess,
sizeof(Bar) == 8
.
Adding virtual functions means creating a virtual table pointer, which adds the pointer size.
123456789101112
class Foo {
	public:
		uint32_t	a_uint;
	public:
		virtual void do_things();
};
class Bar : public Foo {
	public:
		uint32_t	another_uint;
	public:
		virtual void do_stuff();
};

Now
sizeof(Foo) == 8
and
sizeof(Bar) == 12
. Note that Bar has inherited the virtual pointer table requirement and the extra virtual function hasn't added anything to its size!
There's more to it, depending on the compiler, and other modes of inheritance, but that's all I care about for now.
Ches Koblents
October 3, 2014
 
« Newer Older »
© Copyright Koblents.com, 2012-2024