質問の 1 つに回答しているときに、私の回答の下にディスカッション スレッドがありました。これは、アクセス指定子 (または継承のタイプ)に応じprivate/protected/public
てsizeof
、class
オブジェクトが異なる可能性があることを示唆しています!
私は彼らの簡単な議論からまだ理解していません.どうしてそれが可能ですか?
質問の 1 つに回答しているときに、私の回答の下にディスカッション スレッドがありました。これは、アクセス指定子 (または継承のタイプ)に応じprivate/protected/public
てsizeof
、class
オブジェクトが異なる可能性があることを示唆しています!
私は彼らの簡単な議論からまだ理解していません.どうしてそれが可能ですか?
以下の C++11 の新しい言語に注意してください
C++03には、これを可能にする言語、9.2 [class.mem]/12 (私の強調) があります。
access-specifier を介在させずに宣言された (非共用体) クラスの非静的データ メンバーは、後のメンバーがクラス オブジェクト内でより高いアドレスを持つように割り当てられます。アクセス指定子で区切られた非静的データ メンバの割り当て順序は規定されていません(11.1)。実装のアライメント要件により、隣接する 2 つのメンバーが互いの直後に割り当てられない場合があります。仮想関数 (10.3) および仮想基本クラス (10.1) を管理するためのスペースの要件も同様です。
したがって、次の定義が与えられます。
class Foo
{
char a; //8 bits
// a must come before b, so 3 bytes of padding have to go here to satisfy alignment
int b; //32 bits
char c; //8 bits
// 24 bits of padding required to make Foo a multiple of sizeof(int)
};
32 ビット ( ) アラインメントのシステムでは、コンパイラは の前int
に並べ替えることができず、 との間に追加のパディング パディングを強制的に挿入し、オブジェクトの最後に追加します ( を作成します)。ただし、これについては次のとおりです。c
b
a
b
c
sizeof(Foo) == 12
class Foo
{
char a;
public:
int b;
public:
char c;
};
a
と (b
とc
) はアクセス指定子で区切られているため、コンパイラはそのような並べ替えを自由に実行できます。
memory-layout Foo
{
char a; // 8 bits
char c; // 8 bits
// 16 bits of padding
int b; // 32 bits
};
sizeof(Foo) == 8
.
C++11では、言語が若干変更されています。N3485 9.2 [class.mem]/13 は言います (私の強調):
同じアクセス制御(第 11 節) を持つ (非共用体) クラスの非静的データ メンバーは、後のメンバーがクラス オブジェクト内でより高いアドレスを持つように割り当てられます。アクセス制御が異なる非静的データメンバーの割り当て順序は規定されていません(第 11 節)。実装のアライメント要件により、隣接する 2 つのメンバーが互いの直後に割り当てられない場合があります。仮想関数 (10.3) および仮想基本クラス (10.1) を管理するためのスペースの要件も同様です。
これは、C++11 では、上記の例 (3 つの public で区切られている) では、コンパイラが並べ替えを実行できないことを意味します。それは次のようなものでなければなりません
class Foo
{
char a;
public:
int b;
protected:
char c;
};
、a
、b
、およびc
を別のアクセス制御で配置します。
C++11 の規則では、次のような定義があることに注意してください。
class Foo
{
char a;
public:
int b;
protected:
char c;
public:
int d;
};
アクセス指定子で区切られていても、コンパイラは のd
後に配置する必要があります。b
(とは言っても、どちらの標準でも提供される許容範囲を実際に利用する実装については知りません)