今天我们遇到了一个问题,我的代码产生了疯狂的价格。我最终把它归结为我的消息类大小错误的事实,即使我在一个字节上打包并进行单元测试以确保不会发生这种情况。 (事实证明单元测试不是在Windows下运行,但这是另一个问题。)
我有一个traits类模板,除了一些static const
和enum
之外是空的,并且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)
在各种地方,编译器总是说:
1>main.cpp(57): warning C4810: value of pragma pack(show) == 1
修改:使用以下内容显示班级开头的mBuf
偏移量:
cout << "Offset: " << offsetof(NotEmpty4, mBuf) << "\n";
揭示:
Offset: 1