为什么由两个空class导出的空class的大小是2?

Why the size of empty class that is derived from two empty classes is 2?

我知道空class的大小为1只是为了符合不允许对象(及其classes)大小为0的标准。这里,我我得到派生 class D 的大小为 2。为什么在这种情况下行为不同 假设没有从class B和C继承到D的数据成员或虚拟指针?

#include<iostream>
using namespace std;

class A {};
class B : public A {};
class C : public A {};
class D : public B, public C {};

int main() {
    cout<<"Size of D is: "<<sizeof(D)<<endl;
    return 0;
}

对我来说,空碱基优化是否可以应用在这里,取决于人们如何解释 [intro.object/8]:

Unless an object is a bit-field or a base class subobject of zero size, the address of that object is the address of the first byte it occupies. Two objects a and b with overlapping lifetimes that are not bit-fields may have the same address if one is nested within the other, or if at least one is a base class subobject of zero size and they are of different types; otherwise, they have distinct addresses.

BC是不同的类型吗?他们都是A。实际上是两个不同的 A 对象。编译器编写者可以在此处停止分别为 BC 分配存储空间,而无需检查 A 是否为空。

值得注意的是,如果您有 BC 继承自 separate 基础,则使用 g++ 时大小会返回 1:

Live Example

#include<iostream>

class A  {};
class A1 {};
class B : public A {};
class C : public A1 {};
class D : public B, public C {};

int main() {
    std::cout << "Size of D is: " << sizeof(D) << std::endl;
    return 0;
}

这是因为您继承自两个基 class,它们本身派生自相同的基 class A,看看当您更改程序时输出如何变化对此

#include<iostream>
using namespace std;

class A {};
class Z {};
class B : public A {};
class C : public Z {};
class D : public B, public C {};

int main() {
    cout<<"Size of D is: "<<sizeof(D)<<endl;
    return 0;
}

如您所见,D 的大小为 1

该问题与您可能知道的可怕钻石的问题类似。编译器试图消除示例中 DA 的两个实例的歧义。并且这里没有应用空基优化,标准没有要求,编译器也没有实现(见下文)


该标准明确允许编译器不对多继承情况应用空基优化。相关引用自标准 here

Allowing standard-layout classes to have base classes forces compilers to implement the empty base optimization for standard-layout classes, and this could break a compiler's application binary interface (ABI). See 9.2/18 above. This is believed not to be a concern for modern compilers, except possibly in the case of multiple inheritance. Since multiple inheritance is not central to this proposal, allowing standard-layout classes or their bases to use multiple inheritance will be eliminated from the proposal if it proves contentious.