2013-03-17 3 views
7

私はC++プログラミングのより高度な側面のいくつかについて比較的新しく、C++でメモリを割り当てることが真に必要な場合(malloc、newなどを問わず)、問題を理解しています。たとえばCでは、動的に配列された配列やその他のタスクを持つためにメモリを割り当てる必要があることを理解しています。 C++では、そうではないようですが、std :: vector、std :: string、またはすでに設計によって動的にサイズ設定されている他の組み込みメソッドを使用することができます。私はまた、割り当てられたメモリへのアクセスがスタックと比較して遅いことを理解しています。C++:手動でメモリを割り当てることは絶対に必要ですか?

だから、C++でメモリを割り当てる必要があるのですが、そうであればその時代の例は何ですか?これにはもちろん、C++コードとCプログラムとの対話が必要な時は含まれません。プログラムが純粋にC++で書かれているとしましょう。

編集:混乱を緩和しようとすると、ベクターや他の構造が独自のメモリを割り当てていることは理解していますが、これはシーンの裏で起こるもので、プログラマが新しいmallocなどを使用する必要はありません。自動的にクリーンアップされます。だから私が本当に思っているのは、C++で手動でメモリ管理を行う必要があるのか​​どうかです。

+1

'std :: vector'は、動的に割り当てられた配列(通常は"ヒープ "の上)の裏側を管理していることに気付きましたか? –

+0

'vector'が自動的にメモリを割り当てるとき、それは"メモリを割り当てる "と数えられないと言っているように読みます。あれは正しいですか?明示的に 'new' /' delete'を使う必要があるかどうか尋ねていますか? –

+0

@DrewDormannそうです。私はその点を明確にするために質問を編集しました。 –

答えて

8

スタックのサイズは限られています。動的に割り当てられたメモリには、という動的な性質があります。プログラムの実行の瞬間までに、必要な配列やオブジェクトの数が不明な場合があります。

this questionをチェックし、それはそれぞれの可能なユースケースを説明する素晴らしい仕事を行います。

ヒープ割り当て(動的に割り当てられたメモリを)あなたは上記より柔軟になりたい場合に便利です。イベントに応答するために関数が呼び出されることがよくあります(ユーザーが "ボックスを作成"ボタンをクリックします)。適切なレスポンスは、関数が終了してからずっと待たなければならない新しいオブジェクト(新しいBoxオブジェクト)を割り当てる必要があるかもしれないので、スタック上にあることはできません。しかし、あなたはプログラムの最初にいくつのボックスを望むかわからないので、静的にすることはできません。

あなたの編集を反映させるために:確かにそれは本当に必須ではありません、というかvectorstringの場合のように、それは一般的に抽象化されます。あなたはそれを処理するvectorのような様々な容器を持っています。独自のクラスを設計するときは、典型的な手動メモリ管理を抽象化するResource Allocation is Initialization(RAII)というテクニックを採用することをお勧めします。実際には、特にCコードを扱う際に、RAIIを使用するC++クラスラッパーや、C++ 11で導入されたようなC++スマートポインターでそのメモリーを管理することをお勧めします:shared_ptrおよびunique_ptr RAIIを採用しています)。

6

たとえば、Cでは、動的に配列された配列やその他のタスクを割り当てるためにメモリを割り当てる必要があることを理解しています。 C++では、そうではないようですが、std :: vectorや他の組み込みのメソッドを使用することができます。これらのメソッドはすでに設計によって動的にサイズが設定されています。

std::vectorは、内部でメモリを割り当てますが、魔法とフェアリーダストには組み込まれていません。

あなたはC++でその通りですyou rarely need to allocate memory manually。しかし、それは最も簡単な方法ですが、のインスタンスがあります。要点は、デストラクタがそれを処理するので、C++は手動での解放をにする必要がないということです。


非常に、非常にまれ。最もよく書かれたコードは、これをまったく必要としません。低レベルの詳細を処理する場合(コンテナを実装する場合など)には、時には便利です。

1

あなたは自分でする必要はありません。コレクションがスタックにあるが、ヒープ内のすべてのものを置く間、私は常にスタック上にある

void foo(MyStruct&v) { v.bar=1234 } 
vector<MyStruct> v; 
v.push_back(...); 

本質的に単一の値を下回るようなものを行っています。私は大部分のアプリで新しいキーワードやポインタを使用することはありません。

+3

"私はいつも"、 "私は使用していない"この答えは、必要以上に主観的なようです。 3つのフレーズのうち2つは主観的です(「あなたは自分でする必要はありません」)。もっとリアルな*情報でそれを改善してもよろしいですか? – Shoe

6

質問があれば、 "はC++で動的にメモリを必要としませんか?"答えは非常に重要であり、非常に重要です。

ご質問がある場合は、「現代のC++ 11のクラスおよび機能の使用は、どのように頻繁に私のコードは、手動で 『新しい』を使用するために私を必要とし、を削除しますか』」?

これに対する答えは「まれに」です。新しいの大半との通話を削除するには、容器に(のstd ::ベクトルのstd ::マップら)とスマートポインタ(のstd :: shared_ptrのSTDを離れて非表示になります:: unique_ptr)、そしてstd :: make_shared()のような関数を呼び出すことによって、

まれに、「新規」と「削除」を手動で呼び出す必要がありますか?それはあなたが作っているプログラムのタイプにもよりますが、ビデオゲームの場合は、おそらくその1%(私の経験ではありますが、YMMV)、マニュアルを使う必要があります。新しいそして削除のstd :: make_shared オーバー()のstd :: shared_ptrの - 再びかかわらず、それがプロジェクトに依存します。

一般に

、(彼らは内部で動的なメモリを割り当てる場合は無視して)スタックに割り当てられたローカル変数とメンバ変数を好む、次の好むC++ 11が(スマートポインタ)の動的メモリを管理し、最終的には新しいに頼りますは、パフォーマンスが必要な場合には最後の手段として削除します(ただし、プロファイルを事前に最適化して実際のボトルネックを見つけることはできません)。

スマートポインタでメモリを管理しているからといって、コードからすべての生ポインタを禁止する必要はありません。すべてのメモリが管理されていても、無関係な未処理のポインタメモリ寿命管理に

3

あなたが観察してきたように、(などvectormap、)標準コンテナでnewを使用する必要になることはありません

スマートポインタを使用している場合、shared_ptrnewよりmake_sharedを使用するのが無難です。 unique_ptrについては、make_uniqueの不在はすぐに取り組まなければならない欠陥(make_unique and perfect forwarding)である。わかりやすく、例外的な理由から、make_uniquenewよりコピーしてunique_ptrにご自身でコピーしてください。

独自のコンテナを作成する場合は、可能であれば、標準ライブラリ機能(既存のコンテナとスマートポインタ)を作成して、ライフタイム管理を心配する必要がないようにしてください。

newの使用が予想される標準的な機能が1つあります。 std::localeのテンプレート化されたコンストラクタは、std::localeインスタンスによって使用されなくなったときにdelete static_cast<locale::facet*>(f)と処分されるため、デフォルトでFacet *を取るFacet *newによって割り当てられると予測します。 (std::locale::facetには仮想デストラクタがあることに注意してください。)これにより、ファクタを構成するときにrefsパラメータとして1を渡すことで、ファセットのライフタイムを管理することができます。Ownership/delete'ing the facet in a locale (std::locale)

関連する問題