向基类添加默认构造函数会更改派生类型的 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() [重复]的主要内容,如果未能解决你的问题,请参考以下文章