给出示例类
class test
{
public:
test();
~test();
void someMethod();
void someOtherMethod();
private:
int var;
};
是sizeof(test) == sizeof(int)
,还是我们不能做出这样的假设?是平台/编译器依赖吗?
修改
对此的动机是通过流读/写类。类确实包含一个整数,有一些方便的访问方法 - 整数的最高位字节保留用于标志,3个低位字节表示整数24位数。鉴于此,想法是编写这样的类变量的数组,并在需要时将它们读作plain int。引用可能答案的问题没有解决这个问题 - 更多的是关于使用多个元素的填充。
答案 0 :(得分:6)
你无法做出这样的假设。
允许编译器添加填充以提高性能。也许您的目标系统只能读取64位值。读取较小的值需要读取64位然后屏蔽到32位。在这样的系统上,将类填充到64位会更有效。
如果确实需要一个类或结构符合您请求的确切大小,几乎每个编译器都有属性或编译指示来控制填充。
答案 1 :(得分:6)
一般来说,,不,你不能假设某个任意类的大小只是它成员大小的聚合。一般来说,你也不应该关心*。编译器可以并且将改变类的大小,使它们的大小是某个特定字节数的倍数。这样做的原因是为了提高性能。每个平台的字节数是多少。
在这个具体的例子中,事实上可能是sizeof (test)
== sizeof (int)
的情况,但我怀疑这是提示这个问题的真实代码。
有一些方法可以确保它确实如此,但它们依赖于特定于平台的功能。
首先,确保您的课程是POD *,所有成员都是POD。
其次,将打包设置为1个字节。在GCC和MSVC下,执行此操作的说明类似于:
#pragma pack (1)
如果不严格需要,您应该关闭此包装,因为它可能会对性能产生负面影响:
#pragma pack (push, 1)
class test
{
public:
void someMethod();
void someOtherMethod();
int var;
};
#pragma pack (pop)
请注意,上面我删除了private
部分。如果您的类具有非static
private
或protected
数据成员,则该类不是POD。我也出于同样的原因删除了默认的构造函数和析构函数。
在MSVC和GCC下,sizeof(test)
将等于sizeof(int)
。
POD: Plain Old Datatype 。为了使类(或结构)成为POD,它必须没有用户定义的析构函数或构造函数,复制赋值运算符,并且没有非static
成员类型指针成员。此外,它必须没有virtual
,没有private
或protected
非static
成员且没有基类。此外,它拥有的任何非static
数据成员必须也自己是POD。换句话说,只是普通的旧(公共)数据。
“你也不应该关心。”通常,您需要确保某些类的大小与成员的大小完全相同才是系统的边界。例如,通过套接字将数据移入或移出程序时。编译器填充您的类是有原因的。除非您有特定的,可证明的原因,否则不应覆盖此编译器。