web-dev-qa-db-ja.com

スタック/ヒープでのオブジェクトの作成?

次のコードは、スタック上にオブジェクトを作成します。

_Object o;
_

ヒープ上にオブジェクトを作成するとき、次を使用できます。

_Object* o;

o = new Object();
_

のではなく:

_Object* o = new Object();
_

ヒープオブジェクトの作成を2行に分割し、2行目(o = new object())でコンストラクターを呼び出すと、最初の行(_Object* o_)でスタック上にポインターが作成されたことになります? _Object o_はオブジェクトをスタックに配置しますが、_Object* o_は将来のオブジェクトへのポインターをスタックに配置しますか?

2番目の質問は、2行のコードがクラスの外部で呼び出されたかどうかに関するものです。最近、( スタックまたはヒープ内のCでのグローバルメモリ管理? )を読みましたが、グローバル変数はスタック/ヒープに含まれていませんが、実際にはメモリの別の部分ですか?この場合、_Object* o_は、メモリの他の部分に置かれ、ヒープオブジェクトを指すポインタを作成しますか?

46
user997112

実際、どちらのステートメントもヒープやスタックについては何も言っていません。

Object o;

automatic storageでオブジェクトを作成します。これは、オブジェクトが宣言されているコンテキストによって保存場所が決定されることを意味します。コードが関数内にある場合、これはコールスタックになります。ただし、この行はクラスメンバである場合もあれば、既に説明したように関数/クラスの外部である場合もあります。

これが異なる理由を説明するには:

struct Foo {
    Object o;
};

Foo* pf = new Foo();

オブジェクトpf->oが作成されますヒープ上、スタック上ではなく、(またはbecause)に自動ストレージがあります。

逆に、

Object* p;

単にポインタを宣言するだけです。 pointerのストレージは他のオブジェクトと区別できません。自動ストレージがあります。さらに、初期化式は変数ストレージに影響を与えません。

ポインターが指すのはまったく別の問題です。ヒープに割り当てられたオブジェクト(たとえばnewを使用)または自動的に割り当てられた別のオブジェクトを指している可能性があります。考慮してください:

Object o;
Object* p = &o;
87
Konrad Rudolph

C++は、オブジェクトを作成する3つの異なる方法を提供します。

  1. 一時オブジェクトなどのスタックベース
  2. newを使用したヒープベース
  3. グローバル変数や名前空間スコープオブジェクトなどの静的メモリ割り当て

あなたのケースを考えてください、

Object* o;
o = new Object();

そして:

Object* o = new Object();

両方の形式は同じです。これは、ポインター変数oがスタック上に作成され(変数が上記の3つのカテゴリーに属さないと仮定)、オブジェクトを含むヒープ内のメモリーを指すことを意味します。

10
DML

2つの形式は同じですが、1つの例外があります。一時的に、新しい(Object *)は、作成と割り当てが別々の場合、未定義の値を持ちます。未定義のポインターは特に有用ではないため、コンパイラーはそれらを結合して戻す場合があります。これはグローバル変数とは関係ありません(宣言がグローバルでない限り、この場合、両方のフォームに当てはまります)。

4
geekosaur

A)

Object* o;
o = new Object();

`` B)

Object* o = new Object();

AとBに違いはないと思います。どちらの場合も、oはクラスObjectへのポインターです。ステートメントnew Object()は、ヒープメモリからクラスObjectのオブジェクトを作成します。割り当てステートメントは、割り当てられたメモリのアドレスをポインターoに割り当てます。

ヒープから割り当てられたメモリのサイズは、sizeof(Object)+ sizeof(void *)ではなく、常にsizeof(Object)です。

2
user966379

どちらの例でも、Object*タイプのローカル変数がスタックに割り当てられています。プログラムが違いを検出する方法がない場合、コンパイラは両方のスニペットから同じコードを自由に生成します。

グローバル変数のメモリ領域は、静的変数のメモリ領域と同じです-スタックにもヒープにもありません。関数内でstaticを宣言することにより、その領域に変数を配置できます。その結果、インスタンスは関数の同時呼び出し間でsharedになります。そのため、静的を使用する場合は同期を慎重に検討する必要があります。

リンク は、実行中のCプログラムのメモリレイアウトの説明です。

1
dasblinkenlight