2012-07-13 20 views
12

だから、私はC++プログラミングでは非常に新しく、このための決定的な答えを見て数日間見てきました。ヒープとスタックのメンバー変数を宣言する必要はありますか?私が見つけた答えの多くは他の問題に取り組んできましたが、メンバ変数のヒープを使うのが最善で、スタックするのではなくメンバをヒープする方が良い理由を知りたいのです。いつヒープ上のメンバ変数を宣言するのかC++

+1

* member *変数は* class *メンバーを参照し、クラスの*インスタンス*が移動する場所に移動します。 – CapelliC

答えて

18

最初把握するには、2つの重要な概念があります。

  1. 一つは「ヒープ」と「スタック」の観点で考える避けるべきであるが。これは、言語ではなく、コンパイラ/プラットフォームの実装の詳細です。 代わりに、オブジェクトライフタイムの観点から:オブジェクトの寿命がその "親"の寿命に対応しているか、それともそれよりも寿命が長いのでしょうか?後者が必要な場合は、new(直接的または間接的)を使用してオブジェクトを動的に割り当てる必要があります。

  2. メンバー変数常にの親と同じ有効期間があります。メンバ変数はポインタであり、それが指すオブジェクトは独立した有効期間を持つことができます。しかし、指し示すオブジェクトはメンバー変数ではありません。

ただし、あなたの質問に対する一般的な回答はありません。突然言えば、正当な理由がない限り、動的に割り当てないでください。私が上記で示唆したように、これらの理由は、通常、生涯がその「親」と異なる必要がある状況に対応する。


1.実際には、C++標準では実際には「ヒープ」と「スタック」については言及していません。彼らは、パフォーマンスを最適化したり一般的に考えているときに考慮する必要がありますが、プログラム機能の観点からはほとんど関係ありません。

+0

は、通常、生涯が親と異なる必要がある状況に対応しています。「メンバーとして何かについて話すことはできますか? –

+0

@JamesKanze:確かに、私はそれを明確にすべきです。 –

+1

オブジェクトは、動的にサイズを変更する場合や、オブジェクトを仮想基本クラスにキャストする場合にも、動的ライフタイムを必要とします。 –

1

は、call stackを指します。関数呼び出し、戻りアドレス、パラメータ、およびローカル変数は、呼び出しスタックに保持されます。パラメータを渡すか、ローカル変数を作成するたびにスタックメモリを使用します。スタックには一時記憶域しかありません。現在の関数が有効範​​囲外になると、パラメータの変数にアクセスできなくなります。

ヒープは、動的割り当てに使用される大きなメモリプールです。 new演算子を使用してメモリを割り当てると、このメモリはヒープから割り当てられます。現在の関数が終了した後に失いたくないオブジェクトを作成するときにヒープメモリを割り当てたい(スコープを失う)。空白がdeleteまたはfree()で割り当て解除されるまで、オブジェクトはヒープに格納されます。

+0

オブジェクトは、動的にサイズを変更したり、オブジェクトを仮想基本クラスにキャストしたりするために、動的寿命が必要です。 –

4

メンバー変数は、クラス自体のメンバーです。彼らは ヒープ上でもスタック上にもなく、むしろクラス 自身がどこにでもあります。

間接のレベルを追加し、ヒープ上で別々に メンバーを割り当てるための非常にいくつかの理由があります:多型は、(メンバー のタイプは常に同じではない場合)これまでで最も一般的です。

+0

オブジェクトは、動的にサイズを変更する場合や、オブジェクトを仮想基本クラスにキャストする場合にも動的ライフタイムが必要です。 –

+0

@MooingDuck動的にサイズ変更されるオブジェクトは、独自のクラス(例えば、 'std :: vector'など)で管理する必要があります。メンバとして_them_を割り当てず、コンテナをメンバーにします。そして、仮想基底クラスにキャストするか、メンバーが多態的であることを意味するものは、私が言及したものです。 –

+0

申し分ない、十分に –

2

いくつかの用語をまっすぐに理解する:heapおよびstackと呼ぶものは、オブジェクトの有効期間を記述します。第1の意味は、生涯がdynamicであり、第2のautomaticと第3のもの(あなたは言及しない)がstaticであることを意味します。

通常、オブジェクトが作成されたスコープよりも寿命が長くなる必要がある場合は、オブジェクトの有効期間がdynamicになります。別の一般的なケースは、異なる親オブジェクト間で共有される場合です。また、ダイナミックなライフタイムは、重いオブジェクト指向のデザイン(多量の多型を使用し、値を使用しない)で作業する場合にも必要です。 Qt

ダイナミックライフタイムを必要とするイディオムは、pimpl-idiomです。

ほとんどの汎用プログラミングライブラリは、価値と価値セマンティクスの方が重視されているため、動的なバインディングは使用しないでください。

動的割り当てが複数実装具体的な理由のために必要とされるいくつかの例もある。

  • 不完全型を取り扱う動的にサイズのオブジェクト(コンテナ)
  • (PIMPL-イディオムを参照)
  • の容易NULL可能にaタイプ

これらはすべて一般的なガイドラインであり、ケースバイケースで決定する必要があります。一般に、動的オブジェクトよりも自動オブジェクトを優先します。

0

次の例を検討してください。

クラスノードのフィールドメンバーヘッドを持つリンクリストを実装します。
各ノードにフィールドメンバーnextがあります。このNode型のメンバーであり、Node *ではなく各Nodeのサイズがチェーン内のノードの数に依存する場合。

たとえば、リストに100ノードがある場合、ヘッドメンバーは大きくなります。次のノード自体を保持するので、保持するのに十分なサイズが必要であり、次に次のノードを保持する必要があります。だから、頭には99ノードに次の98などを保持するのに十分なスペースが必要です...

この場合、この場合、各ノードの次のノードへのポインタを持つことを避けることをお勧めします。次のノード自体。

関連する問題