web-dev-qa-db-ja.com

C ++:空のクラスのオブジェクトのサイズは?

空のクラスのオブジェクトのサイズがどうなるのかと思っていました。他のオブジェクトのように参照してポイントできるようにする必要があるため、not0バイトにすることはできます。しかし、そのようなオブジェクトはどれくらいの大きさですか?

私はこの小さなプログラムを使用しました:

#include <iostream>
using namespace std;

class Empty {};

int main()
{
    Empty e;
    cerr << sizeof(e) << endl;
    return 0;
}

Visual C++コンパイラとCygwin-g ++コンパイラの両方で得られた出力は、1バイト!マシンのWordのサイズ(32ビットまたは4バイト)であると予想していたので、これは少し驚きでした。

誰も説明することができますなぜ 1バイトのサイズ? なぜない 4バイト?これはコンパイラまたはマシンにも依存していますか?また、空のクラスオブジェクトしないサイズが0バイトである理由について、誰かがより明確な理由を与えることができますか?

101
Ashwin Nanjappa

引用 Bjarne StroustrupのC++スタイルとテクニックに関するFAQ 、サイズがゼロ以外の理由は、「2つの異なるオブジェクトのアドレスが異なることを保証するため」です。また、実際に見るものがないため、ここでは位置合わせは重要ではないため、サイズを1にすることができます。

120
Sol

標準では、ほとんどすべての派生オブジェクトがsizeof()> = 1を持っていると述べています。

ビットフィールド(class.bit)でない限り、最も派生したオブジェクトはゼロ以外のサイズを持ち、1バイト以上のストレージを占有します。基本クラスのサブオブジェクトのサイズはゼロです。 ISO/IEC FDIS 14882:1998(E)intro.object

30
TrayMan

それは本当に実装の詳細です。昔、私はそれがゼロバイトか千バイトかもしれないと思っていました、それは言語仕様に関係がないと。しかし、標準(セクション5.3.3)を見ると、sizeofは、何があっても常に1つ以上を返すように定義されています。

最も派生したクラスのサイズはゼロより大きくなければなりません。

これは、とりわけ、オブジェクトの配列とそれらへのポインターを処理できるようにするために必要です。要素のサイズをゼロにすることが許可されている場合、&(array[0])&(array[42])と同じになり、処理ループにあらゆる種類の混乱をもたらします。

マシンのWordではない理由は、Wordの境界(整数など)に配置する必要がある要素が内部にないためです。たとえば、char x; int y;クラス内で、私のGCCは8バイトでそれを計時します(2番目のintはその実装で整列する必要があるため)。

13
paxdiablo

例外があります:長さ0の配列

#include <iostream>

class CompletlyEmpty {
  char NO_DATA[0];
};

int main(int argc, const char** argv) {
  std::cout << sizeof(CompletlyEmpty) << '\n';
}
6

空のクラスにメモリを割り当てる必要はありませんが、空のクラスのオブジェクトを作成するために、コンパイラは割り当て可能な最小メモリ(1バイト)を割り当てます。このようにして、コンパイラは同じ空のクラスの2つのオブジェクトを一意に区別でき、オブジェクトのアドレスを空のクラスタイプのポインタに割り当てることができます。

5
lalatendu

この良い点を説明する回答にリンクすることも役立つと思います。 それは について boost::compressed_pair by Logan Capaldo

これはuに役立つかもしれません:-) http://bytes.com/topic/c/insights/660463-sizeof-empty-class-structure-1-a

空のクラスまたは構造のサイズは1です

これが標準を適切に実装することに帰着する理由は、C++標準が言うことの1つは、「他の変数と同じアドレスをメモリ内に持つオブジェクトはない」ということです。すべてのタイプのサイズがゼロ以外であることを確認してください。これを実現するために、コンパイラは、データメンバーも仮想関数も持たない構造とクラスにダミーバイトを追加し、サイズが0ではなく1になり、一意のメモリアドレスを持つことが保証されます。

3
Arsalan Mehmood

データメンバはないがサイズが1バイトのクラスの理由は、this * strong text *をメモリに保存して、参照またはポインタがそのクラスのオブジェクトを指すようにする必要があるためです。

2
Ramiz

空のクラスに1バイトを割り当てることはコンパイラに依存します。コンパイラは、オブジェクトが異なるメモリ位置にあることを確認する必要があり、オブジェクトにゼロ以外のメモリサイズを割り当てる必要があります。ここでこのトピックに関するメモを聞いてください: http://listenvoice.com/listenVoiceNote.aspx?id=27

コンパイラーは空のクラスにゼロ以外のサイズを割り当てますが、新しいクラスが空のクラスから派生する場合、最適化も行います。 ListenVoiceのc ++プログラミングインタビューの質問で空のベースの最適化について聞いてください。

2
user332764

空のクラス-そのクラスにはコンテンツが含まれていません。

空でないクラスは、メモリ内のコンテンツによって表されます。

今、空のクラスはメモリでどのように表されますか?記憶にその存在を示す方法はありませんが、クラスが存在するため、記憶にその存在を示すことは必須です。メモリに空のクラスが存在することを示すには、1バイトが必要です。

0
Ganesh
#include<iostream>
using namespace std;


    class Empty { };
    int main()
    {
        Empty* e1 = new Empty;
        Empty* e2 = new Empty;

        if (e1 == e2)
            cout << "Alas same address of two objects" << endl;
        else
            cout << "Okay it's Fine to have different addresses" << endl;

        return 0;
    }

出力:異なるアドレスを使用しても構いません

サイズ1を返すと、2つのオブジェクトが同じアドレスを持たなくなります。

0
Sandeep_black

2つの異なるオブジェクトが異なるアドレスを持つことを保証するためにゼロ以外です。オブジェクトごとにアドレスが異なるため、空のクラスのサイズは常に1バイトです。

0
Yadvendra Yadav

この質問は理論的には興味があるだけで、実際問題ではないと思います。

既に他の人が指摘したように、空のクラスから派生しても害はありません。これにより、基本クラス部分に余分なメモリが消費されることはありません。

さらに、クラスが空の場合(つまり、理論的にはインスタンスごとのメモリを必要としない、つまり、非静的データメンバーまたは仮想メンバー関数を持たない)、すべてのメンバー関数も同様にできます。 (また、静的として定義する必要があります)。したがって、このクラスのインスタンスを作成する必要はありません。

結論:空のクラスXを記述している場合は、すべてのメンバー関数を静的にするだけです。そうすれば、Xオブジェクトを作成する必要がなくなり、派生クラスはまったく影響を受けません。

0
kidfisto

1バイトはプレースホルダーとして使用できる最小のメモリユニットであり、オブジェクトの配列を作成できないため、サイズをゼロにできないためです。

そして、あなたが言ったことは、「マシンのWordのサイズ(32ビットまたは4バイト)であると思っていたので、これは少し驚きでした。」型empty()の参照変数(機械語)に対しては、クラス自体のサイズ(抽象データ型)ではなく、

0
lazarus