違いは何ですか
Kwadrat* k1 = new Kwadrat(1,2,3);
k1->field = 0;
Kwadrat k2(1,2,3);
k2.field = 0;
最初のものは割り当てられたメモリへのポインターであり、2番目のものはオブジェクトです(システムスタックのどこにありますか?) 2番目はなぜ悪いのですか? 最初に使用するとき、2 番目のものはいつ使用しますか?
違いは何ですか
Kwadrat* k1 = new Kwadrat(1,2,3);
k1->field = 0;
Kwadrat k2(1,2,3);
k2.field = 0;
最初のものは割り当てられたメモリへのポインターであり、2番目のものはオブジェクトです(システムスタックのどこにありますか?) 2番目はなぜ悪いのですか? 最初に使用するとき、2 番目のものはいつ使用しますか?
ヒープ上での動的割り当て ( を使用new
):
Kwadrat* k1 = new Kwadrat(1,2,3);
スタック上でのオブジェクト作成 ( なしnew
):
Kwadrat k2(1,2,3);
スタックとヒープに関する詳細な議論については、このスタック オーバーフローの質問を確認してください。ブライアン R. ボンディの回答は 2 つを比較する優れた仕事をしますが、ジェフ ヒルの回答はさらに重要な詳細を提供します。
危険なほど小さな要約の場合:
delete
で作成したオブジェクトを使用する必要があります。new
そうしないと、コードでメモリ リークが発生します。new を使用すると、ヒープ上にオブジェクトが動的に作成されます。つまり、ポインター (k1*) がスコープ外に出てもオブジェクトは保持されます。
これは便利な場合がありますが、範囲外になり、ポインタのコピーを保持しないと、永久に失われ、メモリ リークが発生します。これは、プログラムが実行されている限り、そのリソースが使用するスペースを失うことを意味します。これは、new を使用してメモリを動的に割り当てることの欠点です。追跡し、delete 演算子を使用して手動で解放する必要がありますが、これには余分な作業が必要です。
他の方法で行うと、スコープを離れると破棄されるスタックオブジェクトが作成されます。これは通常望ましいことです。
多くの場合、new で動的メモリ作成を使用する場合、動的に作成されたオブジェクトを別のオブジェクトでラップすることにより、このスタックのような機能を取得しようとします。このオブジェクトは、スコープ外になると破棄されます。このパターンはResource Acquisition is Initialization (RAII)と呼ばれます。これは、オブジェクトをスコープ外に永続化できるため、参照カウントで最も役立ちますが、オブジェクトを参照するものがなくなると破棄されます。
new はヒープにオブジェクトを割り当てます。2 番目の例では、スタックにメモリを割り当てます。k2 を割り当てた関数が返されるとすぐに、メモリは有効ではなくなります (もちろん、k2 のデストラクタが最初に呼び出されます)。オブジェクトを作成した関数よりも長く存続させたい場合は、 new を使用する必要があります。
new
要求する割り当てのストレージを指定できます。経由の割り当てnew/new[]
は通常ヒープ上にありますが (例: ラッピングmalloc
)、最終的には実装によって定義されます。同様に、コンパイラは、場合によってはこれをバイパスするのに十分な情報を持っている可能性があります。
システムスタックのどこにありますか?
技術的には、通常、抽象マシンの仕様に合わせて C++ を記述します。
しかし、通常、はい - オブジェクトはスレッドのスタックに割り当てられます。
なぜ2番目が悪いのですか?最初に使用するとき、2 つ目を使用するときは?
2番目は非常に明確であるため、デフォルトにする必要があります。コンパイラはその寿命と割り当てを管理し、非常に高速です。これに対するいくつかの例外は次のとおりです。
要するに、(2 番目の方法を使用すると) 失敗する可能性がはるかに少なくなり、汎用システム アロケーターを介して割り当てを作成するのに費やされる時間が大幅に短縮されます。