简体   繁体   中英

C++ sizeof operator before and after extending

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) ?

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM