7

Q1。Javaでは、すべてのオブジェクト、配列、およびクラス変数がヒープに格納されますか?同じことがC++にも当てはまりますか?データセグメントはヒープの一部ですか?

C ++の次のコードはどうですか?

class MyClass{
    private:
            static int counter; 
            static int number;
};

MyClass::number = 100;

Q2。私の理解では、コンパイラーによって特定の値が与えられた変数はデータセグメントに格納され、初期化されていないグローバル変数と静的変数はBSS(シンボルで始まるブロック)に格納されます。この場合、静的であるMyClass :: counterはコンパイラによってゼロに初期化されるため、BSSに格納され、100に初期化されたMyClass::numberはデータセグメントに格納されます。私は結論を出すのに正しいですか?

Q3。次のコードを検討してください。

void doHello(MyClass &localObj){   
// 3.1 localObj is a reference parameter, where will this get stored in Heap or Stack?
      // do something
}

void doHelloAgain(MyClass localObj){   
// 3.2 localObj is a parameter, where will this get stored in Heap or Stack?
      // do something
}

int main(){
      MyClass *a = new MyClass();  // stored in heap

      MyClass localObj;   
      // 3.3 Where is this stored in heap or stack?
      doHello(localObj);
      doHelloAgain(localObj);
}

私の質問をすべての人に明確にしたことを願っています

編集:

BSSの理解については、この記事を参照してください

編集1:クラス名が不適切な名前だったため、クラス名をMyInstanceからMyClassに変更しました。心からお詫び申し上げます

EDIT2:クラスメンバーの変数番号を非静的から静的に変更しました

4

5 に答える 5

6

これはやや単純化されていますが、私の知る限りではほとんど正確です。

Javaでは、すべてのオブジェクトがヒープに割り当てられます(すべてのメンバー変数を含む)。他のほとんどのもの(パラメーター)は参照であり、参照自体は、ネイティブ型よりもオブジェクトである文字列を除いて、ネイティブ型(int、longなど)とともにスタックに格納されます。

C ++では、「new」キーワードを使用してすべてのオブジェクトを割り当てる場合、Javaとほぼ同じ状況になりますが、代わりにスタックにオブジェクトを割り当てることができるため、C ++には1つの固有のケースがあります(常にではありません)。 「新規」を使用する必要があります)。

また、JavaのヒープパフォーマンスはCのヒープパフォーマンスよりもCのスタックパフォーマンスに近いことに注意してください。ガベージコレクターはかなり賢いことをします。それでもスタックほど良くはありませんが、ヒープよりはるかに優れています。Javaはスタックにオブジェクトを割り当てることができないため、これが必要です。

于 2009-08-26T18:23:35.400 に答える
2

Q1

Javaも変数をスタックに格納しますが、クラスインスタンスはヒープに割り当てられます。C ++では、クラスインスタンスをスタックまたはヒープのいずれかに自由に割り当てることができます。キーワードを使用してnew、インスタンスをヒープに割り当てます。

データセグメントはヒープの一部ではありませんが、プロセスの開始時に割り当てられます。ヒープは動的メモリ割り当てに使用されますが、データセグメントは静的であり、内容はコンパイル時に認識されます。

BSSセグメントは、初期化されていない、またはゼロに初期化されていないデータセグメントに属するすべてのデータ(文字列、定数など)がBSSセグメントに移動される単純な最適化です。データセグメントは実行可能ファイルに埋め込まれている必要があり、「すべてのゼロ」を最後に移動することで、実行可能ファイルから削除できます。実行可能ファイルがロードされると、BSSセグメントが割り当てられ、ゼロに初期化されます。コンパイラは、BSSセグメント内のさまざまなバッファ、変数などのアドレスを引き続き知ることができます。

Q2

MyClass::numberMyClassクラスのインスタンスが割り当てられている場所に格納されます。ヒープ上またはスタック上にある可能性があります。Q3で、スタックに割り当てられている間にヒープaに割り当てられたインスタンスを指す方法に注目してください。したがって、スタック上にある間、ヒープ上にあります。MyClasslocalObja->numberlocalObj.number

インスタンス変数と同様MyClass::numberに、次のように割り当てることはできません。

MyClass::number = 100;

MyClass::counterただし、静的であるため(プライベートを除く)、割り当てることができます。

MyClass::counter = 100;

Q3

doHello変数localObj(in )を呼び出すと、main参照によって渡されます。の変数は、スタック上のその変数を参照しますlocalObj。変更すると、 inが割り当てられdoHelloているスタックに変更が保存されます。localObjmain

呼び出すとdoHelloAgain、変数localObj(in main)がスタックにコピーされます。内部doHelloAgainの変数localObjはスタックに割り当てられ、呼び出しの間のみ存在します。

于 2009-08-26T18:13:55.950 に答える
1

Q1。Javaでは、すべてのオブジェクト、配列、およびクラス変数がヒープに格納されますか?同じことがC++にも当てはまりますか?データセグメントはヒープの一部ですか?

いいえ、データセクションはヒープから分離されています。基本的に、データセクションはロード時に割り当てられ、その後はすべて固定の場所になります。さらに、オブジェクトをスタックに割り当てることができます。

オブジェクトがヒープ上にあるのは、キーワードを使用する場合、または関数ファミリーのnew何かを使用する場合のみです。malloc

Q2。私の理解では、コンパイラによって特定の値が与えられた変数はデータセグメントに格納され、初期化されていないグローバル変数と静的変数はBSS(シンボルで始まるブロック)に格納されます。この場合、静的であるMyInstance :: counterはコンパイラによってゼロに初期化されるため、BSSに格納され、100に初期化されたMyInstance::numberはデータセグメントに格納されます。私は結論を出すのに正しいですか?

はい、BSSセクションの理解は正しいです。ただし、numberコードは静的ではないため、次のようになります。

MyInstance::number = 100;

は合法ではありません。静的にするか、コンストラクターで適切に初期化する必要があります。コンストラクターで初期化すると、所有オブジェクトが割り当てられている場所に存在します。静的にすると、データセクションに表示されます...どこかにある場合。多くの場合static const int、変数は、グローバル変数がまったく必要ないように、使用されるコードに直接インライン化できます。

Q3。次のコードを検討してください:..。

void doHello(MyInstance &localObj){

localObjは、渡されたオブジェクトへの参照です。あなたが知っている限り、ストレージはありません、それは渡される変数がどこにあるかを指します。実際には、内部では、これを容易にするためにポインタをスタックに渡すことができます。しかし、コンパイラーは、可能であれば、それを簡単に最適化することができます。

void doHelloAgain(MyInstance localObj){

渡されたパラメーターのコピーがスタックに配置されます。

MyInstance localObj;
// 3.3 Where is this stored in heap or stack?

localObjはスタック上にあります。

于 2009-08-26T18:14:57.990 に答える
1

C ++では、オブジェクトはスタックに割り当てられる場合があります...たとえば、Q3メインルーチンのlocalObjです。

クラスとインスタンスについて混乱を感じます。「MyInstance」は、クラス名よりも変数名として意味があります。Q1の例では、「number」はタイプMyInstanceの各オブジェクトに存在します。「カウンター」はすべてのインスタンスで共有されます。「MyInstance::counter = 100」は有効な割り当てですが、「number」メンバーを割り当てるオブジェクトを指定していないため、「MyInstance :: number=100」は有効ではありません。

于 2009-08-26T18:20:09.213 に答える
1

C++のすべてのメモリ領域がここに一覧表示されます

于 2009-08-26T19:52:27.060 に答える