0

私は、を持っていstd::vector<SomeType>ますSomeTypeが、はstructさまざまなテンプレートパラメータからインスタンス化されています。

最終的に私の特定のケースでは、それは大きな構造(約1MB)であることが判明しました。このような構造をスタックに割り当てる(つまり、このタイプの自動変数を使用する)と、すぐにスタックオーバーフローが発生します。ただしstd::vector、メモリはヒープに割り当てられるため、問題はありません。

驚いたことに、これに問題があります。具体的には、問題は初期化にあります。私は次のことをします:

std::vector<SomeType> myVec;
// ...
myVec.resize(N);
for (size_t i = 0; i < N; i++)
{
    SomeType& x = myVec[i];
    // initialize it
}

でスタックオーバーフロー例外が発生しmyVec.resize()ます。resize()デバッガーを使用して内部に入ると、が大きくresize()なる場合はvector、メモリを割り当てるだけでなく、「デフォルト値」によって新しい要素を初期化することもわかりました。

「デフォルト値」は、指定されたタイプの自動変数を作成し、デフォルトの(つまり空の)コンストラクターを使用して、それに新しい要素を割り当てることによって取得されます。

これを克服する方法があるのだろうか。std::vectorつまり、新しい要素を初期化しないように指示します。しかし、不要なコードを生成せずにこれを実現したいと思います。

vector(スマート/共有/スコープ/一意の)ポインターを使用して入力することを考えることができます。または、代わりに使用しますpush_backが、新しい各要素はヒープに割り当てられます。しかし、これは避けられないことですが、余分なコードが必要です。これは正当化されません。

必要なことを達成する方法はありますか?一方:

  • まだ使用していますstd::vector<SomeType>
  • 冗長なヒープ割り当てはありません

前もって感謝します

4

3 に答える 3

4

C++03 では不可能です:

  • ベクトルに初期化されていない要素を含めることはできません
  • ベクトルはコピーによって要素を初期化する方法しか知らない

したがって、コピー元の要素が必要です。スタックに収まらず (デフォルトの引数を除外)、明示的に他の場所に配置したくないため、運が悪いです。

C++11 では、コンテナー内の要素を初期化する新しい手段があり、たとえば、size_tコンストラクターは余分な既定の引数を取りません。代わりに、各要素の値を初期化します。これはおそらくあなたが望むものです。

したがって、C++11 では、答えはstd::vector<SomeType> myVec(N);. おそらく、コンパイラにコードのコンパイルに使用できる C++11 モードがあるかどうかを確認できます。もちろん、C++11 への移行は簡単ではありません。

于 2012-07-31T12:54:39.747 に答える
2

reserve を使用してから push_back を使用します。

于 2012-07-31T12:49:40.663 に答える
2

最善の解決策は、SomeTypeサイズが小さくなるように変更することです。ただし、スタックやヒープを使用せずにベクトルのサイズを変更することは可能です。静的ローカル変数を使用するだけです:

static SomeType intialValue;
myVec.resize(N, initialValue);

そのような関数は再入可能ではないことに注意してください。

于 2012-07-31T13:02:45.697 に答える