3

给定示例类

class test
{
public:
test();
~test();
void someMethod();
void someOtherMethod();

private:
int var;
};

sizeof(test) == sizeof(int),或者我们不能做出这样的假设?它依赖于平台/编译器吗?

编辑:

这样做的动机是通过流读/写类。类确实包含一个整数,并带有一些方便的访问方法 - 整数的最高位字节保留用于标志,3 个低位字节表示整数 24 位数。鉴于此,想法是编写此类变量的数组,并在需要时将它们作为纯 int 读取。引用为具有可能答案的问题并未解决该方面 - 更多的是关于填充多个元素。

4

2 回答 2

7

一般来说,不,您不能假设某个任意类的大小只是其成员大小的聚合。一般来说,你也不应该关心*。编译器可以并且将更改您的类的大小,以便它们的大小是某些特定字节数的倍数。这样做的原因是为了提高性能。每个平台的字节数是不同的。

在这个具体的例子中,实际上可能是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: 普通旧数据类型。为了使类(或结构)成为 POD,它必须没有用户定义的析构函数或构造函数、复制赋值运算符,并且没有指向成员的非static成员类型指针。此外,它必须没有virtuals、没有private或非protected成员static,也没有基类。此外,它所拥有的任何非数据成员static必须是 POD 本身。换句话说,只是普通的旧(公共)数据。


“你也不应该在意。” 通常,您需要确保某个类的大小与成员的大小完全相同的唯一时间是在系统的边界处。例如,当通过套接字将数据移入或移出程序时。编译器填充你的类是有原因的。除非您有特定的、可证明的原因,否则您不应在此覆盖编译器。

于 2013-07-11T16:27:19.330 回答
6

你不能做出这样的假设。

允许编译器添加填充以提高性能。也许您的目标系统只能读取 64 位值。读取较小的值需要读取 64 位,然后屏蔽为 32 位。在这样的系统上,将类填充到 64 位会更有效。

如果您确实需要一个类或结构的大小与您请求的确切大小相同,那么几乎每个编译器都有属性或编译指示来控制填充。

于 2013-07-11T16:25:16.110 回答