8

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

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

編集:混乱を緩和するために、ベクトルやその他の構造が独自のメモリを割り当てていることを理解していますが、これは舞台裏で行われ、プログラマーがnewやmallocなどを使用する必要がなく、自動的にクリーンアップされます。だから私が本当に疑問に思っているのは、C++で手動でメモリ管理を実行する必要があるということです

4

5 に答える 5

8

スタックのサイズには制限があり、一部のスタックは確実に収まりません。動的に割り当てられたメモリには動的な性質もあり、プログラムの実行のある時点まで、配列内に必要なオブジェクトまたは要素の数がわからない場合があります。

この質問をチェックしてください、それはそれぞれの可能なユースケースを説明する素晴らしい仕事をします:

ヒープ割り当て(動的に割り当てられたメモリ)は、上記よりも柔軟にしたい場合に役立ちます。多くの場合、イベントに応答するために関数が呼び出されます(ユーザーが[ボックスの作成]ボタンをクリックします)。適切な応答には、関数が終了した後もずっと続くはずの新しいオブジェクト(新しいBoxオブジェクト)を割り当てる必要がある場合があります。そのため、関数をスタックに置くことはできません。ただし、プログラムの開始時に必要なボックスの数がわからないため、静的にすることはできません。

あなたの編集を反映するために:確かにそれは実際には必要ではなく、むしろ、との場合のように通常は抽象化されていvectorますstring。あなたはあなたのためにそれを処理するような様々なコンテナを持っていvectorます。独自のクラスを設計するときは、一般的な手動のメモリ管理を抽象化するリソース割り当ては初期化(RAII)の手法を採用することをお勧めします。実際、特定の場合、特にCコードを扱う場合は、RAIIを使用するC ++クラスラッパー、またはC++11で導入されたようなC++スマートポインターを使用してそのメモリを管理することをお勧めしshared_ptrますunique_ptr。 RAIIを採用)。

于 2013-03-17T23:50:21.450 に答える
7

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

std::vectorただし、魔法や妖精の粉の上に構築されているわけではありません。内部でメモリを割り当てます。

C ++では、メモリを手動で割り当てる必要はほとんどありません1でも、それが最も簡単な方法である場合があります。重要なのは、C ++では、デストラクタが処理するため、手動による割り当て解除が完全に不要になるということです。


1非常に、非常にまれです。ほとんどのよく書かれたコードはこれをまったく必要としません。下位レベルの詳細を処理する場合(たとえば、コンテナーを実装する場合)に役立つことがあります。

于 2013-03-17T23:56:43.340 に答える
6

C++では動的に割り当てられたメモリは不要ですか?」という質問の場合、答えは非常に必要であり、非常に重要であるということです。

質問が「最新のC++11クラスと機能を使用している場合、コードで「new」と「deleteを手動で使用する必要がある頻度はどれくらいですか?」

その答えは、「まれに」です。new呼び出しとdelete呼び出しのほとんどは、コンテナー( std :: vectorstd :: mapなど)とスマートポインター(std::shared_ptrstd::unique_ptr)に隠され、 std: :make_shared()

まれに、「new」と「delete」を手動で呼び出す必要がありますか?作成しているプログラムの種類によって異なりますが、ビデオゲームの場合は、おそらく1%の確率で(私の経験ではありますが、YMMV)、手動でnewを使用し、 stdを削除する必要があります。 :: make_shared()std :: shared_ptr-繰り返しになりますが、プロジェクトによって異なります。

一般に、スタックに割り当てられたローカル変数とメンバー変数を優先し(動的メモリを内部で割り当てるかどうかは無視します)、次にC ++ 11マネージド動的メモリ(スマートポインター)を優先し、最後にnewに頼り、最後の手段として削除します。パフォーマンスにはそれが必要です(ただし、事前に最適化しないでください-プロファイルを作成し、実際のボトルネックを見つけてください)。

スマートポインタを使用してメモリを管理しているからといって、コードからすべてのrawポインタを禁止する必要があるわけではありません。すべてのメモリが管理されている場合でも、メモリの有効期間の管理とは関係のないrawポインタが実際に使用されています。 。

于 2013-03-18T00:33:12.477 に答える
3

newご覧のとおり、標準のコンテナ(、、など)で使用するvector必要mapはありません。

スマートポインタを使用する場合は、;make_sharedよりも常に使用する方が適切です。がないため、すぐに対処する必要がある欠陥(make_uniqueおよび完全な転送)があります。明確さと例外の安全性の理由から、自分自身にコピーして貼り付けて使用することをお勧めします。newshared_ptrunique_ptrmake_uniquemake_uniquenewunique_ptr

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

newの使用が期待される標準的な施設が1つあります。std::localeFacet *デフォルトで使用するテンプレート化されたコンストラクターは、インスタンスによって使用されなくなると破棄されるため、Facet *によって割り当てられることを想定しています。(仮想デストラクタがあることに注意してください。)これで不快な場合は、ファセットを構築するときにパラメータとして渡すことで、ファセットの存続期間を自分で管理するように調整できます。ロケールでのファセットの所有権/削除(std :: locale )newdelete static_cast<locale::facet*>(f)std::localestd::locale::facet1refs

于 2013-03-18T11:15:29.193 に答える
1

あなたは自分自身にする必要はありません。私はいつも以下のようなことをしました

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

コレクションがスタックにある間、本質的に単一の値がスタックにありますが、すべてをヒープに入れます。ほとんどのアプリで新しいキーワードやポインターを使用することはありません。

于 2013-03-18T00:09:02.100 に答える