今日、私のコードが異常な価格を生成するという問題が発生しました。最終的には、1 バイトでパックし、これが起こらないように単体テストを実施しているにもかかわらず、メッセージ クラスのサイズが間違っていたという事実に要約しました。(単体テストは Windows で実行されていないことが判明しましたが、それは別の問題です。)
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
編集: wrt のオフセットをmBuf
クラスの先頭に表示する:
cout << "Offset: " << offsetof(NotEmpty4, mBuf) << "\n";
明らかに:
Offset: 1