今天我们遇到了一个问题,我的代码产生了疯狂的价格。我最终将其归结为我的消息类的大小错误,即使我正在打包一个字节并进行了单元测试以确保这种情况永远不会发生。(原来单元测试没有在 Windows 下运行,但这是另一个问题。)
我有一个特征类模板,除了一些static const
s 和enum
s 之外它是空的,以及一个为空的noncopyable
类的实现。
当我从上述两个派生一个类时,生成的类被填充 1 个字节,但仅在 Windows 下,并且只有当我从这两个类派生时。如果我从其中一个派生,则不会填充该类。
我意识到我在这里使用#pragma
.
问题是:为什么在空类的多个公共继承的情况下,MSVC 将类填充 1 个字节?
这是一个解决问题的 SSCCE:
#include <cstdlib>
#include <string>
#include <iostream>
using namespace std;
#pragma pack (1)
template <size_t ExpectedSize>
class Traits
{
public:
static const size_t mExpSize = ExpectedSize;
};
class noncopyable
{
public:
noncopyable() {};
~noncopyable() {};
private:
noncopyable& operator= (const noncopyable&);
noncopyable (const noncopyable&);
};
class NotEmpty1
{
public:
char mBuf [33];
};
class NotEmpty2
:
public Traits <33>
{
public:
char mBuf [33];
};
class NotEmpty3
:
public noncopyable
{
public:
char mBuf [33];
};
class NotEmpty4
:
public Traits <33>,
public noncopyable
{
public:
char mBuf[33];
};
int main()
{
cout << "Case 1: " << sizeof (NotEmpty1) << "\n"
<< "Case 2: " << sizeof (NotEmpty2) << "\n"
<< "Case 3: " << sizeof (NotEmpty3) << "\n"
<< "Case 4: " << sizeof (NotEmpty4) << "\n"
;
}
这里的想法是所有NotEmpty
类都正好是33 个字节。在 linux 下(使用 G++ 4.4.6.4)它们是:
Case 1: 33
Case 2: 33
Case 3: 33
Case 4: 33
在 Windows 下(使用 MSVC 9 和 10)它们不是:
Case 1: 33
Case 2: 33
Case 3: 33
Case 4: 34
编辑: 当我使用:
#pragma pack (show)
在各种 pf 地方,编译器总是说:
1>main.cpp(57): warning C4810: value of pragma pack(show) == 1
编辑:mBuf
使用以下方法显示类开头的 偏移量:
cout << "Offset: " << offsetof(NotEmpty4, mBuf) << "\n";
揭示:
Offset: 1