24

From what i know, the size of a class in c++ depends on the below factors -

  1. Size of all non-static data members.
  2. Order of data members.
  3. If byte padding is enabled or not.
  4. Size of its immediate base class.
  5. The existence of virtual functions.
  6. Mode of inheritance (virtual inheritance).

Now I've created 2 classes as below -

class A{
    int a;
    short s;
    int b;
    char d;
};// kept a char at last on purpose to leave a "hole"

class B : public A{
    char c;  
};

now on checking the size of A and B I see

  • size of A: 16
  • size of B: 16

my assumption is the char c in class B is accommodated in "hole" left in class A.

But, whats confused me is the below scenario wherein I make the members public

class A{
    public:
    int a;
    short d;
    int b;
    char s;
};

class B : public A{
    public:
    char c;
};

Now the size becomes

  • size of A: 16
  • size of B: 20

I cannot seem to understand the reason for this difference.

Eric
  • 95,302
  • 53
  • 242
  • 374
J.DOE
  • 291
  • 2
  • 7
  • 1
    *Why does the size of class in c++ depend on the public/private status of data members?* -- It doesn't. Those are compiler-dependent implementation details. – PaulMcKenzie Nov 20 '19 at 17:42
  • 1
    So what compiler are you using? – Romen Nov 20 '19 at 17:42
  • 2
    @PaulMcKenzie Actually it does. The standard mandates members with the same access get grouped together so changing that will change the padding strategy of the compiler. – NathanOliver Nov 20 '19 at 17:43
  • @NathanOliver-ReinstateMonica, I didn't know that. Do you have a reference to the relevant section handy by any chance? – R Sahu Nov 20 '19 at 17:45
  • @RSahu Looking it up to put in my answer tight now. – NathanOliver Nov 20 '19 at 17:46
  • Perhaps, a public member can be accessed by external code that may have differing alignment requirements, so "worst case" alignment is used. When the member is private the compiler has visibility of all accesses so has greater flexibility. I am not sure that really explains it, but padding and alignment are implementation dependent so to know you'd have to consider the constraints of the target, the generation of the code, and the design decisions of the compile author. Not sure it is worth worrying about - there never were any guarantees. – Clifford Nov 20 '19 at 17:48
  • Is it intentional that you've changed the names of `s` and `d` between the two examples? – TLW Nov 21 '19 at 03:21
  • I'd tried this on g++ version - g++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-36) but when i tried the same on Intel compiler icpc- icc (ICC) 19.0.4.243 20190416 i got consistent results irrespective of the changes in the access specifiers – J.DOE Nov 21 '19 at 08:01

1 Answers1

9

The Itanium ABI uses the C++03 definition of POD to define classes that are "POD for the purposes of layout". Having private data members disqualifies a class from being an aggregate and therefore POD in C++03:

A POD-struct is an aggregate class that has no non-static data members of type non-POD-struct, non-POD-union (or array of such types) or reference, and has no user-defined copy assignment operator and no user-defined destructor.

Being a POD class disables tail padding reuse:

The dsize, nvsize, and nvalign of these types are defined to be their ordinary size and alignment. These properties only matter for non-empty class types that are used as base classes. We ignore tail padding for PODs because an early version of the standard did not allow us to use it for anything else and because it sometimes permits faster copying of the type.

Thus, in your first example, A is not a POD for layout purposes and its tail padding can be used for B::c, but in your second example, it is a POD, and its tail padding cannot be reused.

T.C.
  • 133,968
  • 17
  • 288
  • 421