【问题标题】:Understanding different padding rules between gcc/clang vs msvc2015 when inheriting multiple empty classes [duplicate]继承多个空类时了解gcc/clang vs msvc2015之间的不同填充规则[重复]
【发布时间】:2018-09-10 16:28:08
【问题描述】:

当涉及到 gcc/clang 与 msvc2015 中空类的多重继承时,我看到了不同的行为。我想知道是否有人会知道标准中的哪些内容允许这种差异。

#include <cstdint>
using namespace std;

class Empty1 {};
static_assert(sizeof(Empty1) == 1, "Expected size of 1 for Empty1");

class Empty2 {};
static_assert(sizeof(Empty2) == 1, "Expected size of 1 for Empty2");

class Empty3 : Empty2, Empty1 {};
static_assert(sizeof(Empty3) == 1, "Expected size of 1 for Empty3");

class Int1 { uint32_t i; };
static_assert(sizeof(Int1) == 4, "Expected size of 4 for Int1");

class Int2 : Empty1 { uint32_t i; };
static_assert(sizeof(Int2) == 4, "Expected size of 4 for Int2");

class Int3 : Empty2 { uint32_t i; };
static_assert(sizeof(Int3) == 4, "Expected size of 4 for Int3");

class Int4 : Empty3 { uint32_t i; };
static_assert(sizeof(Int4) == 8, "Expected size of 8 for Int4");
static_assert(sizeof(Int4) == 4, "Expected size of 4 for Int4");

此代码,在 msvc2015 上生成:

error C2338: Expected size of 4 for Int4

而 gcc 和 clang 会生成这个:

error: static_assert failed "Expected size of 8 for Int4"

也就是说,msvc2015从空类继承时不会添加任何字节,但从多个类继承时会添加。 C++ 中有未定义的行为吗?

【问题讨论】:

  • 空基优化就是:一种优化。编译器不必这样做
  • 所以当没有空基优化时的预期行为是空基有 1 个字节,然后 3 个填充用于对齐,然后 4 个用于uint32_t = 总共 8 个字节?

标签: c++ struct multiple-inheritance


【解决方案1】:

默认情况下,MSVC 不进行此优化,因此它编译的代码可以与旧版本的编译器 ABI 兼容。但是,if you use __declspec(empty_bases),您可以告诉 MSVC 启用此优化:

#ifdef _MSC_VER
#define EBO_ENABLE __declspec(empty_bases)
#else
#define EBO_ENABLE
#endif

class EBO_ENABLE Empty3 : Empty2, Empty1 {};
static_assert(sizeof(Empty3) == 1, "Expected size of 1 for Empty3");

Live on Godbolt

【讨论】:

  • 太棒了。似乎 msvc 的默认行为是优化第一个空类,然后为每个额外添加 1 个字节。添加 6 个空类后,我的 sizeof()8 -> 12 增长。我不知道这可以在 msvc 中配置,谢谢!
猜你喜欢
  • 2016-01-23
  • 2021-10-10
  • 1970-01-01
  • 1970-01-01
  • 2017-11-25
  • 2016-01-08
  • 1970-01-01
  • 2020-04-14
  • 1970-01-01
相关资源
最近更新 更多