首页 > 解决方案 > C ++多重继承增加了类的大小?

问题描述

好吧,我在 C++、MSVC 编译器中遇到了一个奇怪的行为。

如果你写

struct Class1 {};
struct Class2 : Class1 {};
struct Class3 : Class2 {};
struct Class4 : Class3 {};

asizeof(Class4)将返回 1,a 预期。但是如果你写

struct Class1 {};
struct Class2 {};
struct Class3 {};
struct Class4 : Class1, Class2, Class3 {};

sizeof(Class4)运行时将是两个。IntelliSenseconstexpr auto x = sizeof(Class4)并将指示值 1,但我遇到了一些模板技巧,它报告大于 1 的值,它们甚至与实际运行时值不匹配。

阅读论坛我发现了这个:

如果您从一个空类继承,但编译器的 ABI 不允许该类与该类的其他部分重叠其布局,则该类的大小也会由于纯填充而增加。考虑将 C++20(即将推出)属性 [[no_unique_address]] 作为替代方案。

我知道,但我仍然觉得奇怪的是行为会根据我使用的继承实现而改变。对这个问题有什么想法吗?

编辑:

对于最小的可重现示例:

// "Sequential" inheritance
struct S0 {};
struct S1 : S0 {};
struct S2 : S1 {};

struct S3 : S2 {

    int val;
    int foo() { return val; }
};

// "End" inheritance
struct E0 {};
struct E1 {};
struct E2 {};

struct E3 : E0, E1, E2 {

    int val;
    int foo() { return val; }
};

int main() { 

    S3 s = S3();
    E3 e = E3();

    std::cout << sizeof(s) << "\n" << sizeof(e) << "\n" << (sizeof(s) == sizeof(e));
    return 0;
}

哪个打印出来

4
8
0

所以类 S3 的实例有sizeof4,但 E3 的实例有sizeof8。最终的问题是为什么。为什么这两个类,S3 和 E3,根据继承的方式有不同的大小?

编辑2:

差点忘了,我所说的运行时和编译时是什么意思,虽然程序执行返回了这些值,但如果您在之前添加的代码下方

constexpr auto sizS3 = sizeof(S3);      // IntelliSense report 4, prints 4
constexpr auto sizE3 = sizeof(E3);      // IntelliSense report 4, prints 8
constexpr auto equal = sizS3 == sizE3;  // IntelliSense report true, prints false (0)

IntelliSense 将报告这两个值都是 4U,但打印这些值与打印实例S3 sE3 e.

解决方案:

所以,在研究了更多之后,发现了这个问题:为什么空基类优化(EBO)在 MSVC 中不起作用?

struct __declspec(empty_bases) E3 : E0, E1, E2 {

    int val;
    int foo() { return val; }
};

将按预期工作。

标签: c++inheritance

解决方案


推荐阅读