52

いくつかのメンバー変数を持ち、仮想関数を持たない基本クラスがあるとします。

class Base {
   int member;
};

非仮想的な方法で派生し、Base新しいメンバー変数を持たず、仮想関数も持たない派生クラス:

class Derived : Base {
};

明らかsizeof(Derived)に より小さくすることはできませんsizeof(Base)

sizeof(Derived)に等しい必要がありsizeof(Base)ますか?

4

4 に答える 4

18

5.3.2 から [expr.sizeof]

クラスに適用すると、結果 [of sizeof] は、そのクラスのオブジェクトのバイト数であり、そのタイプのオブジェクトを配列に配置するために必要なすべてのパディングを含みます。最も派生したクラスのサイズはゼロ (1.8) より大きくなければなりません。

1.8から [intro.object]

それがビットフィールド (9.6) でない限り、最も派生したオブジェクトはゼロ以外のサイズを持ち、1 バイト以上のストレージを占有するものとします。基本クラスのサブオブジェクトは、サイズがゼロの場合があります。POD 型 (3.9) のオブジェクトは、ストレージの連続するバイトを占有します。

とメモ:

基本クラスのサブオブジェクトの実際のサイズは、サブオブジェクトに sizeof を適用した結果よりも小さい場合があります。これは、仮想基本クラスと、基本クラスのサブオブジェクトのパディング要件がそれほど厳しくないためです。

sizeofこれらをまとめると、結果がゼロよりも大きくなる以外に、何を伝えるかについて何の保証もないということを伝えていると思います. 実際、それを保証しているようにも見えませんsizeof(Derived) >= sizeof(Base)!

于 2013-11-13T09:34:31.867 に答える
10

興味深い質問です。余分なフィールドを持つ派生クラスが空の基本クラスと同じサイズある例があります。 (これはコメントである必要がありますが、大きすぎます。興味深い場合は賛成票を歓迎しますが、他の回答のいずれかを受け入れてください。)

次の簡単な C++ プログラムについて考えてみましょう。

class A {};

class B : public A {
    int m_iInteger;
};

int _tmain(int argc, _TCHAR* argv[])
{
    printf("A: %d\r\n", sizeof(A));
    printf("B: %d\r\n", sizeof(B));
    printf("int: %d\r\n", sizeof(int));

    return 0;
}

4の場合、出力は何になると思いますsizeof(int)か? おそらく次のようなものです:

A: 0
B: 4
int: 4

?

私のコンパイラ - Embarcadero C++ Builder 2010 - の出力は次のとおりです。

A: 8
B: 8
int: 4

つまり、派生クラスにフィールドを追加しても、派生クラスは大きくなりません。

互換性オプション Zero-length empty base classに関するヘルプ ファイルのトピックで、その理由についての洞察が得られます。

通常、クラスがデータ メンバーを定義していない場合でも、クラスのサイズは少なくとも 1 バイトです。このオプションを設定すると、コンパイラは、メモリ レイアウトおよび派生クラスの合計サイズに対して、この未使用のバイトを無視します。空の基本クラスは、派生クラスのスペースを消費しません。デフォルト = 偽

このコンパイラの既定のコンパイラ設定を使用したクラスのサイズは 1 バイトではなく 8 バイトのようです。実際、このコード例でこの設定を変更しても効果はありません。

基本クラスのサイズと上記の最適化に関するこの記事も興味深いものです。クラスが少なくとも 1 バイトのサイズを持たなければならない理由、最適化が行うこと、およびメンバー関数の表現などについて詳しく説明します。

実際、標準では、オブジェクトのサイズが決してゼロにならないように要求しています。また、派生オブジェクトでは、基本クラスのデータ メンバーが派生クラスのユーザー宣言データ メンバーの前に現れる必要があります。ただし、基本クラスのサブオブジェクトは完全なオブジェクトとは見なされません。したがって、ルールに違反することなく、派生オブジェクトから基本クラスのサブオブジェクトを削除することができます。つまり、オブジェクト t では、S と x のオフセットが重なる可能性があります...

その引用の完全なコンテキストについては、記事をお読みください。

于 2013-11-13T09:45:59.930 に答える
-1
class Base {
 // int member;            I have just created an empty base class.
};

class Derived : Base {
};

現在、gcc コンパイラは、Base クラスと Derived クラスによって作成されたオブジェクトの両方に対して "size>0" を指定します。gcc コンパイラは、オブジェクトのアドレスの存在をユーザーに提供するだけです。

  Note:Derived class would contain base class members, so obviously we can think of 
  sizeof(derived class) greater then sizeof(base class). But this depends on the compiler 
  if it allocates some extra space while defining the derived class. 

私の現在の gcc コンパイラは、Base と Derived の両方のオブジェクトのサイズが同じであることを示しました。

于 2013-11-13T10:59:28.147 に答える