向基类添加默认构造函数会更改派生类型的 sizeof() [重复]

Posted

技术标签:

【中文标题】向基类添加默认构造函数会更改派生类型的 sizeof() [重复]【英文标题】:Adding a default constructor to a base class changes sizeof() a derived type [duplicate] 【发布时间】:2017-12-20 21:29:02 【问题描述】:

我倾向于认为我对 C++ 内部结构和内存布局有很好的掌握,但这一点让我感到困惑。我有以下测试代码:

#include <stdio.h>

struct Foo

    //Foo() 
    int x;
    char y;
;

struct Bar : public Foo

    char z[3];
;

int main()

    printf( "Foo: %u Bar: %u\n", (unsigned)sizeof( Foo ), (unsigned)sizeof( Bar ) );

输出合理:

Foo:8 小节:12

然而,这是非常奇怪的部分,如果我取消注释 Foo() 上的简单默认构造函数,sizeof(Bar) 会发生变化!添加 ctor 怎么可能改变这些类的内存布局?

Foo:8 小节:8

使用 gcc-7.2 编译

【问题讨论】:

也许是因为它不再是一个聚合? 如果您删除构造函数但添加public:,您将看到同样的问题,至少对于 GCC。我认为 MSVC 不会给你这个。问题是一旦结构开始使用 C++ 特性,它就不再是 POD 类型了。 它不再是标准布局,因此不再是 POD,只要你有父和子都有成员变量。 @M.M 我可以想到几个原因(例如,正如其他人指出的那样,添加构造函数会使结构不是 POD),但我承认我不明白为什么这会减少对象的大小。向结构添加 public: 规范不会,AFAIK,阻止它成为 POD。 我怀疑答案在 itanium-cxx-abi.github.io/cxx-abi/abi.html#class-types 某处,它指定了 gcc 使用的 C++ ABI(gcc 将此 ABI 规范用于除 Itanium 之外的其他架构) 【参考方案1】:

GCC 遵循适用于 C++ 的 Itanium ABI,可防止用于存储派生类数据成员的 POD 的尾部填充。

添加用户提供的构造函数意味着Foo 不再是POD,因此该限制不适用于Bar

See this question 了解有关 ABI 的更多详细信息。

【讨论】:

以上是关于向基类添加默认构造函数会更改派生类型的 sizeof() [重复]的主要内容,如果未能解决你的问题,请参考以下文章

生成一个派生类对象时,调用基类和派生类构造函数按啥次序

虚函数总结

在派生类的构造函数中初始化没有默认构造函数的基类

阿里笔试题-派生类构造函数 创建顺序

继承

基类构造函数的派生类成员初始化