ベクトルが割り当てられると、それらはヒープまたはスタック上のメモリを使用しますか?


151

次の説明はすべて正しいですか?

vector<Type> vect; //allocates vect on stack and each of the Type (using std::allocator) also will be on the stack

vector<Type> *vect = new vector<Type>; //allocates vect on heap and each of the Type will be allocated on stack

vector<Type*> vect; //vect will be on stack and Type* will be on heap. 

どのようにメモリがために内部的に割り当てられているType中でvector、または任意の他のSTLコンテナ?


回答:


221
vector<Type> vect;

vector、つまりヘッダー情報をスタックに割り当てますが、要素は空きストア(「ヒープ」)に割り当てます。

vector<Type> *vect = new vector<Type>;

無料のストアにすべてを割り当てます。

vector<Type*> vect;

vectorスタックにを割り当て、空きストアに一連のポインタを割り当てますが、これらのポイントはそれらの使用方法によって決まります(たとえば、要素0を空きストアにポイントし、要素1をスタックにポイントすることができます)。


3
しかし、2番目の宣言でTypeが大きくなるとセグメンテーション違反が発生するというシナリオがあります。Typeがスタックに割り当てられていたためだと思いました。
Phelodas

4
@Phelodas:コードを見ずにこれを評価することは不可能です。新しい質問を開いてください。
Fred Foo

2
vector<Type> vect;要素は、ヒープ上にあり、ヘッダ情報は、ヘッダ情報を関数の戻り値と同様に、メモリから削除されたスタック、上にあるため、どのような要素の思い出に起こるのだろうか?それらはヘッダー情報で再利用されますか?そうでない場合、これはメモリリークを引き起こしますか?
フライレイン2013

3
@flyrain:ベクターは後片付けを行います。RAIIを読んでください。
Fred Foo

1
@flyrain:うまくいくはずです。詳細を記載した新しい質問を投稿してください。ここにリンクを貼って頂ければご覧になるかもしれません。
Fred Foo

24
vector<Type> vect; //allocates vect on stack and each of the Type (using std::allocator) also will be on the stack

いいえ、vectスタックにありますが、アイテムを格納するために内部で使用する配列はヒープにあります。アイテムはその配列に常駐します。

vector<Type> *vect = new vector<Type>; //allocates vect on heap and each of the Type will be allocated on stack

いいえvector。クラスもヒープ上にあることを除いて、上記と同じです。

vector<Type*> vect; //vect will be on stack and Type* will be on heap. 

vectスタック上にあり、その項目(へのポインターType)はヒープ上にありType、ポインターが指すs がどこにあるかはわかりません。スタック上、ヒープ上、グローバルデータ内、どこにもない可能性があります(NULLポインタなど)。

ちなみに、実装では実際に一部のベクトル(通常は小さいサイズ)をスタック全体に格納できます。そのような実装について私が知っているわけではありませんが、それは可能です。


23

実際にスタックとヒープがある実装を想定すると(標準C ++はそのようなことを要求しません)、真のステートメントは最後のものだけです。

vector<Type> vect;
//allocates vect on stack and each of the Type (using std::allocator) also will be on the stack

これは、最後の部分を除いて当てはまります(Typeスタックには含まれません)。想像してみてください:

  void foo(vector<Type>& vec) {
     // Can't be on stack - how would the stack "expand"
     // to make the extra space required between main and foo?
     vec.push_back(Type());
  }

  int main() {
    vector<Type> bar;
    foo(bar);
  }

同様に:

 vector<Type> *vect = new vector<Type>; //allocates vect on heap and each of the Type will be allocated on stack

最後の部分を除いて真であり、同様のカウンターの例があります:

  void foo(vector<Type> *vec) {
     // Can't be on stack - how would the stack "expand"
     // to make the extra space required between main and foo?
     vec->push_back(Type());
  }

  int main() {
    vector<Type> *bar = new vector<Type>;
    foo(bar);
  }

ために:

vector<Type*> vect; //vect will be on stack and Type* will be on heap. 

これは真実ですが、Type*ポインタはヒープ上にありますが、Typeそれらが指すインスタンスは必ずしもそうである必要はないことに注意してください。

  int main() {
    vector<Type*> bar;
    Type foo;
    bar.push_back(&foo);
  }

どのような状況でスタックがありませんか?標準では必要としないとおっしゃっていますが、実際には、スタックがないのはいつですか。
Nerdtron

3
@Nerdtron-一部の小さなマイクロコントローラーのIIRCには、最後の呼び出しの時点でPC(プログラムカウンター)以外を何も格納できない呼び出しスタックがあり、RETの準備ができています。したがって、コンパイラーは、「自動ストレージ」(非再帰関数の場合)を、実行のフローとほとんど関係なく、固定された場所に配置することを選択する場合があります。それはプログラム全体をかなり賢く平らにすることができました。再帰的な場合でも、「関数ごとのスタック」ポリシーまたは自動変数と戻りアドレス用の個別のスタックを使用できるため、「スタック」というフレーズは少し意味がなくなります。
Flexo

すべてにヒープベースの割り当てを使用し、自動ストレージを管理する「クリーンアップスタック」を使用できます(場合によってはそれdeleteも)。
Flexo

3

このステートメントだけが真です:

vector <Type*> vect; //vect will be on stack and Type* will be on heap.

Type* ポインターの量は動的に変化する可能性があるため、ポインターはヒープに割り当てられます。

vect この場合、ローカルスタック変数として定義したため、スタックに割り当てられます。


2
Type *はヒープの割り当てを示すものではなく、単にTypeオブジェクトへのポインタです。そうは言っても、ベクトルはポインターをヒープに格納します。int a = 5; int * ptr_to_a =&a; vector <int *> vec; vec.push_back(ptr_to_a); (jpalecekの回答を参照してください)
マシューラッセル

1

ベクターは、内部有するallocatorからメモリの割り当てを解除する/割り当てる担当するheapためにvector element。したがって、どのようにベクトルを作成しても、そのベクトルelementは常にに割り当てられheapます。ベクターのメタデータは、作成方法によって異なります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.