1
// main.cpp

class Cat()
{
public:
     Cat()
     {
          a = 0;
          (*b) = 0;
     }

     int a;
     int* b;
};

int main(int argc, char* argv[])
{
     Cat cat1;
     Cat* cat2 = new Cat();
     return 0;
}

ふだんは記憶なんてどうでもいいcat1のですが、はっきりと理解したいのですが、 と と はどのような記憶cat2の中ab存在するのでしょうか。スタックまたはヒープ内?

@BoPerson: そうです、私はb = new int(0). しかし、私にとってもっと興味深いのはa、オブジェクトCatがヒープに作成されたときに変数はどこにあるのでしょうか? aヒープにも?ヒープ内のポインタbもヒープ内のメモリを指していますよね?

4

3 に答える 3

8

その場で注釈を付けて回答させてください。

クラスキャット()
{
公衆:
     ネコ()
     {
          = 0; // ok: 変数 a が存在する場所に設定します
          (*b) = 0; // ダメ: 整数 0 を b が指している場所に格納します
                    // b は何にも初期化されていないため、書き込み可能
                    // どこでも想像できます。運が良ければ、コンパイラ
                    // ポインターを暗黙的にゼロに初期化します。
                    // 少なくとも確定的なセグメンテーション違反を取得します。
     }

     int a; // Cat が構築される場所ならどこにでも存在する整数変数
     int* b; // Cat が構築される場所ならどこにでも存在するポインタ変数
             // (b = 何か) に設定される場所は、ヒープ、スタック、
             // マップされたメモリ、制御不能 (ここのように)
};

int main(int argc, char* argv[])
{
     猫 cat1; // cat1 をスタックに割り当て、すべての属性 (a と b) を有効にします
               // そこの。cat1.b が指す場所は無制限です。
     Cat* cat2 = new Cat(); // Cat クラスのオブジェクトをヒープに割り当て、
               // ポインタ変数 cat2 をスタックに割り当て、
               // ヒープに割り当てられた Cat へのポインタ
               // 繰り返しますが、cat2.b が指す場所は無制限です。
     0 を返します。// segfault が原因で到達できなかった可能性があります ;-)
}

タイトルでメモリ管理について言及しているように、スタック変数はスコープ外になると自動的に破棄されます。cat1つまり、 and (1 つの Cat と 1 つのポインター)によって占有されていたスペースは、cat2main() を終了するときに回復されます。また、cat1 の場合、デストラクタが呼び出されます。あなたの場合、明示的なデストラクタはありませんが、Cat にデストラクタを持つ属性がある場合、自動デストラクタが自動生成されます。

ポインターの場合、ポインターが破棄されても、指しているオブジェクトは自動的に破棄されません。それが必要な場合は、std::auto_ptr<> (または Qt の QScopedPoiner) のようなスマート ポインターを確認する必要があります。これは、ポイント先のオブジェクトを実際に破棄する (delete を呼び出すことによって) ポインターのようなオブジェクトを提供します。 auto_ptr が破壊されたとき。

スマート ポインターを使用しない場合は、delete 演算子を使用して、ポイント先のオブジェクトを手動で破棄するように注意する必要があります。現在のスコープからのすべてのリターンパスでそれを行うように注意してください(複数のリターン、スローされた例外など)。

于 2011-02-26T12:18:47.747 に答える
4

new キーワードは、オブジェクトをヒープに割り当てます。最初の例ではメモリをスタックに割り当てました。

Cat cat1; //stack

Cat* cat2 = new Cat(); //heap

スタック メモリは、ヒープ メモリほどすぐには利用できません。基本的に、新しいメモリをヒープに格納し、そのアドレスをポインタに格納します。

ヒープ上のメモリも削除できます。「削除」コマンドを使用します。これにより、プログラムがより効率的に実行されます。

私は誰かの重要な指針を見逃していますか?

編集:ヒープ上のメモリは、効率性のためだけでなく、プログラムの膨張を避けるために、使用されなくなったときに削除する必要があります。(メモリ リーク) - ありがとう @Felice Pollano

于 2011-02-26T11:35:40.413 に答える
1

cat1はスタックに割り当てられます。クラスは8バイトです(プラットフォーム上でintとpointersが4バイトの場合)。最初の4バイトは整数aです。次の4バイトは整数bです。

cat2はヒープメモリに割り当てられます。それ以外は上記とまったく同じです。

スタック変数は「スコープ」されます。これは、スタックフレームがポップされたとき(つまり、関数を終了したとき)に解放され、そのデコンストラクターが呼び出されることを意味します。

一方、ヒープ変数は、メモリを「削除」するまでハングします。

また、構築されたものが不正であることに注意してください。「*b」はポインターを逆参照します(つまり、ポインターが指しているデータも取得します)。次に、0を割り当てます。発生する問題は、bが決定されたメモリを指していないため、プロセスのアドレス空間にない可能性のある不明なメモリ位置に0を書き込んでいることです。私はあなたが本当に「b=NULL;」を意味すると思ったでしょう。

于 2011-02-26T11:41:13.757 に答える