Ok, you have a class C like this:
class C
{
int c;
int d;
};
An instance of class C (C c
) will occupy some memory, it needs (provided int is 4 bytes large - this is not necessarily the case on all machines, though) 8 bytes.
If an instance is located at address 0x248544, it will occupy exactly the byte at this address + the next subsequent ones. In such a simple class as above with out any further conditions, c will occupy the first four of these eight bytes, d the next four ones.
So c.c
has exactly the same address as your object c
, and c.d
is located four bytes afterwards, so will have address 0x248548.
Be aware, though, that the first member does not necessarily have the same address as your object! Lets modify our class C:
class C
{
virtual ~C() { } // virtual destructor -> C gets virtual!
int c;
int d;
};
Now, sizeof(C) will be 16(!) (provided pointers require 8 bytes storage, as on modern 64-bit hardware). Why? The class gets an additional pointer to a vtable, which is normally the first (but invisible) member of class C.
So c
will still be at address 0x248544, but now the (invisible) pointer to vtable shares this address; c.c
comes afterwards, thus is located at address 0x2484c and c.d
then is located at 0x24850.
In this respect, C++ is different from C, where the first member of a struct always shares the address of the struct itself...
Both in C and C++, though, two subsequent members do not necessarily have to "touch" each other, there might be some bytes padded in between - keyword byte alignment.
Additionally, C++ allows to reorder the members of a class:
Whereas in C, if struct member a
is declared before b
, then a
must be placed in front of b
in memory, too, this is in C++ only required for members of the same accessibility!
class C
{
int a;
public:
int b;
private:
int c;
};
The compiler now is allowed leave the order as is, but it could as well place b
in front of or after the other two - only a
is not allowed to be placed after c
.
Long story, short conclusion: All this memory layout stuff is much more complicated than you probably expected it to be...
Side note to vtables: The vtable pointer is not required to be there (in respect to the C++ standard) - if any compiler vendor finds a better solution to implement polymorphism, they are free to do so - if they find... But vtables are the current state of the art, kind of de-facto standard.