Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ sizeof operator before and after extending

Tags:

c++

sizeof

I am now testing the result of C++ sizeof operator:

class S{};
class A:public S{
    virtual void fun()=0;
};
class B{};
class C : public B,public A {};

int main(){
     cout<<sizeof(A)<<endl;// result is 4
     cout<<sizeof(C)<<endl;// result is 8
} 

But if I remove the extend of class S:

class A{
    virtual void fun()=0;
};
class B{};
class C : public B,public A{};

int main(){
    cout<<sizeof(A)<<endl;// result is 4
    cout<<sizeof(C)<<endl;// result is 4
} 

Can anyone explain the different of the output of sizeof(C) in those two examples? Class S is just an empty class (I know, sizeof(S) == 1), so why does it make a difference whether or not A has a base class? Especially since it doesn't make any difference to sizeof(A), only to sizeof(C)?

like image 243
wuchang Avatar asked Oct 08 '14 13:10

wuchang


Video Answer


2 Answers

It seems that VS can't handle properly a situation when there are more than one empty base classes. In your first example theres is one empty base class, and in the second there are two. For example on my box this code compiled on VS2013:

#include <iostream>

class B1 {};
class B2 {};
class B3 {};
class B4 {};
class B5 {};
class B6 {};

class C1 : B1 {};
class C2 : B1, B2 {};
class C3 : B1, B2, B3 {};
class C4 : B1, B2, B3, B4 {};
class C5 : B1, B2, B3, B4, B5 {};
class C6 : B1, B2, B3, B4, B5, B6 {};

int main() {
    std::cout << sizeof(C1) << ' ' << sizeof(C2) << ' ' << sizeof(C3) << ' '
        << sizeof(C4) << ' ' << sizeof(C5) << ' ' << sizeof(C6) << std::endl;
}

outputs

1 1 2 3 4 5

While both clang and gcc output 1 1 1 1 1 1.

But this behavior is still standard compliant, because the standard doesn't oblige the implementation to optimize empty base classes away.

like image 123
Anton Savin Avatar answered Oct 24 '22 22:10

Anton Savin


It seems that in Multiple Inheritance, Visual Studio reserves at least 1 byte for every empty class.

With default alignment of 4 bytes, this leads to class C being 8 bytes.

But this may serve a purpose.

With multiple inheritance, C class looks like this:

B Part

S Part

A Part

C Part

The reservation allows getting different identities for the parts as follows:

C c1;
printf("address of S part %ld\n",static_cast<S*> (&c1));  // prints 4651208
printf("address of B part %ld\n",static_cast<B*> (&c1));  // prints 4651209 with one byte alignment
like image 1
Gonen I Avatar answered Oct 24 '22 22:10

Gonen I