单独继承的派生类的大小
Posted
技术标签:
【中文标题】单独继承的派生类的大小【英文标题】:Size of singly inherited derived classes 【发布时间】:2016-07-11 10:01:04 【问题描述】:以下代码 (online version) 基于 Stanley Lippman 所著的“C++ 对象模型内部”一书的第 3.4 节(参见硬拷贝的第 85-86 页或PDF version 的第 64 页)。
#include <iostream>
#include <cstddef> // defines offset
struct Base
int w;
char x;
;
struct Derived1 : Base
char y;
;
struct Derived2 : Derived1
char z;
;
int main()
std::cout << "sizeof(Base) = " << sizeof( Base ) << "\n";
std::cout << "sizeof(Derived1) = " << sizeof( Derived1 ) << "\n";
std::cout << "sizeof(Derived2) = " << sizeof( Derived2 ) << "\n";
std::cout << "Offset of x in Derived2 = " << offsetof( Derived2 , x) << "\n";
std::cout << "Offset of y in Derived2 = " << offsetof( Derived2 , y) << "\n";
std::cout << "Offset of z in Derived2 = " << offsetof( Derived2 , z) << "\n";
根据文本 Derived2 应该(?)大小为 16 个字节(假设是 32 位机器),但在 gcc 上我得到 12 个字节。然而,在 Visual Studio 上,它的大小正确(?)报告为 16 个字节。这是一个 gcc 回归错误还是标准没有定义的东西?
编辑
Stanley Lippman 确实不使用了offsetof
宏。这是我做的。
【问题讨论】:
我只想说gcc
在填充方面比visual studio
做得更好。关于对象应该如何表示,没有标准的说法。这取决于实施。
您正在阅读 1996 年的版本,那是两个 十年 前,甚至比 C++ 的第一个标准版本发布早两年。尝试查找最新版本;不要太害羞而实际购买适当的教育材料。
我相信 GCC('s ABI) 不必要地在桌面上留下了优化空间。在 64 位和 32 位 x86 上,所有三个类都可以轻松地具有相同的大小 8,方法是将其布局为 4+1+1+1+padding。不过,我认为 Itanium ABI 不允许这样做。
检查 link 以了解填充规则是否适用于您的代码。
【参考方案1】:
宏offsetof
只能用于标准布局 类型。由于Derived1
和Derived2
都没有标准布局,因此您的行为是未定义的。
除此之外,C++ 标准并没有对非静态数据成员的布局做出任何特别的承诺,因此如果一个布局与您对另一个布局的期望不符,这并不是真正的“错误”。
【讨论】:
令李普曼失望!以 UB 为例,和假设x
的填充量!为他辩护,这本书写于 1996 年……
提供的代码似乎很标准。我猜想使用offsetof
的问题只出现在多重继承和虚拟继承中。
@Arunmu:不,Kerrek 是对的;这些类不符合 standard-layout 的定义。阅读§9/7。
@LightnessRacesinOrbit 哦..谢谢!以上是关于单独继承的派生类的大小的主要内容,如果未能解决你的问题,请参考以下文章