19

経験豊富なC++ユーザーから、ヒープ変数の使用に努めるべきだと言われました。

A* obj = new A("A");

とは対照的に:

A obj("A");

ポインターの使用に関するすべてのことを除けば、スタックよりもヒープに物を置く方が良いと彼は言いました(スタックがヒープよりも小さいということはありますか?)。それは本当ですか?もしそうなら、なぜですか?

NB:私は生涯の問題について知っています。これらの変数の存続期間を適切に管理したと仮定しましょう。(つまり、懸念される唯一の基準は、ライフタイムの懸念がないヒープとスタックのストレージです)

4

8 に答える 8

15

コンテキストに応じて、ヒープまたはスタックを検討できます。すべてのスレッドはスタックを取得し、スレッドは関数を呼び出すことによって命令を実行します。関数が呼び出されると、関数変数はスタックにプッシュされます。そして、関数がスタックのロールバックを返し、メモリが再利用されると。現在、スレッドローカルスタックにはサイズ制限がありますが、サイズはさまざまであり、ある程度調整することができます。これを考慮すると、すべてのオブジェクトがスタック上に作成され、オブジェクトが大きなメモリを必要とする場合、スタックスペースが使い果たされ、スタックオーバーフローエラーが発生します。これに加えて、オブジェクトが複数のスレッドによってアクセスされる場合、そのようなオブジェクトをスタックに格納することは意味がありません。

したがって、小さな変数、サイズの小さなオブジェクトはコンパイル時に決定でき、ポインタはスタックに格納する必要があります。オブジェクトをヒープまたはフリーストアに格納することの懸念は、メモリ管理が困難になることです。メモリリークの可能性がありますが、これは悪いことです。また、アプリケーションがすでに削除されているオブジェクトにアクセスしようとすると、アクセス違反が発生し、アプリケーションがクラッシュする可能性があります。

C ++ 11では、ヒープを使用したメモリ管理を容易にするスマートポインター(共有、一意)が導入されています。実際に参照されるオブジェクトはヒープ上にありますが、常にスタック上にあるスマートポインターによるカプセル化です。したがって、関数の戻りイベント中または例外中にスタックがロールバックすると、スマートポインターのデストラクタがヒープ上の実際のオブジェクトを削除します。共有ポインタの場合、参照カウントは維持され、参照カウントがゼロになると実際のオブジェクトは削除されます。 http://en.wikipedia.org/wiki/Smart_pointer

于 2012-06-02T08:14:30.190 に答える
9

スタック割り当て変数とヒープ割り当て変数の使用に関する一般的な規則はありません。あなたがやろうとしていることに応じて、ガイドラインだけがあります。

ここにいくつかの長所と短所があります:

ヒープ割り当て:

長所:

  • より柔軟-コンパイル時に利用できない情報がたくさんある場合
  • サイズが大きい-より多く割り当てることができます-ただし、無限ではないため、割り当て/割り当て解除が正しく処理されない場合、ある時点でプログラムのメモリが不足する可能性があります

短所:

  • 遅い-動的割り当ては通常、スタック割り当てよりも遅い
  • メモリの断片化を引き起こす可能性があります-異なるサイズのオブジェクトの割り当てと割り当て解除により、メモリはスイスチーズのように見えます:)必要なサイズのメモリブロックが利用できない場合、一部の割り当てが失敗します
  • 維持するのが難しい-各動的割り当ての後に割り当て解除を行う必要がありますが、これはユーザーが行う必要があります-これは、すべてのmalloc()呼び出しをfree( )delete()を使用してまたはnew()を呼び出す

スタック割り当て:

長所:

  • より高速-これは主に組み込みシステムで重要です(組み込みには動的割り当てを禁止するMISRAルールがあると思います)
  • メモリの断片化を引き起こしません
  • アプリケーションの動作をより決定論的にします-たとえば、ある時点でメモリが不足する可能性を排除します
  • エラーが発生しにくい-ユーザーが割り当て解除を処理する必要がないため

短所:

  • 柔軟性が低い-コンパイル時にすべての情報(データサイズ、データ構造など)を利用できるようにする必要があります
  • サイズが小さい-ただし、アプリケーションの合計スタックサイズを計算する方法があるため、スタックの不足を回避できます

これは賛否両論のいくつかを捉えていると思います。きっともっとあると思います。

結局、それはあなたのアプリケーションが何を必要としているかに依存します。

于 2012-06-02T08:52:55.250 に答える
8

スタックに割り当てられた変数は自動変数であるため、スタックはヒープよりも優先される必要があります。プログラムがコンテキストから外れると、それらの破棄は自動的に行われます。

実際、スタックとヒープで作成されたオブジェクトの寿命は異なります。

  • 関数またはコードブロック{}(newによって割り当てられていない)のローカル変数は、スタック上にあります。関数から戻ると、それらは自動的に破棄されます。(それらのデストラクタが呼び出され、それらのメモリが解放されます)。
  • ただし、関数の外部で使用するオブジェクトが必要な場合は、ヒープに(newを使用して)割り当てるか、コピーを返す必要があります。

例:

 void myFun()
 {
   A onStack; // On the stack
   A* onHeap = new A(); // On the heap
   // Do things...

 } // End of the function onStack is destroyed, but the &onHeap is still alive

この例でonHeapは、関数の終了時にメモリが割り当てられたままになります。そのため、onHeapどこかにポインタがないと、それを削除してメモリを解放することはできません。プログラムが終了するまでメモリが失われるため、メモリリークです。

onStackただし、関数を終了するときに破棄されたため、にポインタを返す場合、onStackポインタを使用すると未定義の動作が発生する可能性があります。使用中onHeapはまだ完全に有効です。

スタック変数がどのように機能しているかをよりよく理解するには、ウィキペディアのこの記事など、呼び出しスタックに関する情報を検索する必要があります。関数で使用するために変数をスタックする方法について説明します。

于 2012-06-02T07:18:07.973 に答える
4

C ++では、できるだけ新しいものを使用しないようにすることをお勧めします。
ただし、避けられない場合があります。
例:
変数がスコープを超えて存在することを望んでいます。

したがって、実際にはコースの馬である必要がありますが、選択肢がある場合は、ヒープに割り当てられた変数を常に避けてください。

于 2012-06-02T06:27:22.757 に答える
1

答えは、一部の人が信じるほど明確ではありません。

一般に、自動変数(スタック上)を選択する必要があります。これは、単純に簡単だからです。ただし、状況によっては(ヒープ上で)動的な割り当てが必要になります。

  • コンパイル時のサイズが不明
  • 拡張可能(コンテナは内部でヒープ割り当てを使用します)
  • 大きなオブジェクト

後者は少し注意が必要です。理論的には、自動変数は無限に割り当てられる可能性がありますが、コンピューターは有限であり、さらに悪いことに、ほとんどの場合、スタックのサイズも有限です(これは実装の問題です)。

個人的には、次のガイドラインを使用しています。

  • ローカルオブジェクトは自動的に割り当てられます
  • ローカル配列は延期されstd::vector<T>、内部的に動的に割り当てられます

それは私によく役立っています(これは明らかに逸話的な証拠です)。

注: RAII(スマートポインターまたはコンテナー)を使用して、動的に割り当てられたオブジェクトの存続期間をスタック変数の存続期間に関連付けることができます(おそらくそうすべきです)。

于 2012-06-02T13:46:08.187 に答える
0

C ++には、ヒープまたはスタックについての言及はありません。言語に関する限り、それらは存在しない/別個のものではありません。

実用的な答えとしては、最も効果的なものを使用してください。迅速に必要ですか。保証が必要ですか。アプリケーションAはヒープ上のすべてのものではるかに優れている可能性があり、アプリケーションBはOSメモリを断片化する可能性があるため、マシンを強制終了します-正しい答えはありません:-(

于 2012-06-02T07:23:30.520 に答える
0

簡単に言えば、必要がない限り、自分の記憶を管理しないでください。;)

于 2012-06-02T09:16:43.737 に答える
-4

スタック=コンパイル時に割り当てられた静的データ。(動的ではありません)

ヒープ=実行時に割り当てられた動的データ。(非常に動的)

ポインターはスタック上にありますが...これらのポインターは、動的で自発的なデータ作成の扉を開くので美しいです(プログラムのコーディング方法によって異なります)。

(しかし、私はただの野蛮人なので、なぜ私が言うことが重要なのですか)

于 2014-08-08T00:20:18.317 に答える