4

Good time of day!

I wrote some code, but I cannot understand some strange memory anomalies. Could anybody, who has a proper knowledge in class memory using give me a explanation?

My code:

#include <iostream>

using namespace std;

class O
{
    O();
    ~O();
};

class A
{
public:
    A();
    ~A();
    void someFunc();
private:
    int m_a;
};

class B: public A
{
public:
    B();
    virtual ~B();
private:
    int m_b;
};

class C: public B
{
public:
    C();
    ~C();
private:
    char m_c;
};

int main()
{
    cout << sizeof(char) << endl;
    cout << sizeof(int) << endl;
    cout << sizeof(O) << endl;
    cout << sizeof(A) << endl;
    cout << sizeof(B) << endl;
    cout << sizeof(C) << endl;
    cin.get();
    return 0;
}

output:

1  //normal for char
4  //normal for int on x32
1  //why empty class occupies 1 byte?
4  //int m_a.  Where is 1 byte?
12 //4B virtual function, 8B - m_a and m_b.
16 //char needs 1 byte. Why it gets 3 more?

Thank you for attention and answers )

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
Fairyteller
  • 312
  • 1
  • 10
  • "Strange anomalies"? As opposed to all those ordinary, every-day anomalies? :-) – Kerrek SB Sep 17 '13 at 20:57
  • This is all normal. The standard demands objects are never 0 bytes. The 3 padding bytes are there for alignment, used when you put objects of type C in an array. – Hans Passant Sep 17 '13 at 21:02

2 Answers2

5
  • Empty class: Every complete object must have a unique address. Consider EmptyClass a[10], and the fact that array elements are complete objects, and consider how pointer arithmetic works.

  • int m_a? Your assumption is unwarranted. There's no need for an extra dummy byte if you already have meaningful bytes.

  • C: Padding. Again, consider arrays and alignment. Class C will have the alignment of int, and every array member of C a[10] must be aligned, and array members must be contiguous.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • thank you all. But what value will that lonely byte get? And I add one more char field to C, and size had not changed, you are right =) – Fairyteller Sep 17 '13 at 21:04
  • 1
    @Fairyteller: The value is indeterminate, and generally none of your business. If you're curious, you can always print it out, but it's meaningless and doesn't satisfy any constraints (it might change every ten clock cycles, say). – Kerrek SB Sep 17 '13 at 21:08
  • Thank you one more time. Can you recommend me any books about memory organization and "under the hood" C++ ? – Fairyteller Sep 17 '13 at 22:13
  • @Fairyteller: I don't know... you could try our [definitive recommended book list](http://stackoverflow.com/q/388242/596781), or you might as well read it up in the standard. But I think there's really not that much to it: object have alignment requirements (built transitively from the alignment requirements of the fundamental types), an arrays are laid out contiguously with no padding. And every object (complete or not) is determined precisely by the pair (address, type). That should allow you to deduce almost everything. – Kerrek SB Sep 18 '13 at 07:56
1

O (Empty Class): In order to address the class, it has to have at least 1 byte of space allocated to it. You cannot address anything smaller than a byte.

A (Class with single int member): Its members add up to a single integer's worth of space. That is all it needs and there are no alignment issues.

B (Decrived class with another int member and a vtable): It's space requirement will be determined by both the 2 ints and the vtable. Hence the extra 4 bytes (pointer to the vtable on a 32bit machine).

'C' (Derived class with another char): It has all the stuff from B, and 1 byte (the char), plus 3 more to make it align properly.

Zac Howland
  • 15,777
  • 1
  • 26
  • 42