オブジェクトがスタック上にあるべきかどうかを識別する方法は?
-
03-07-2019 - |
質問
C ++でスタックまたはヒープにオブジェクトを割り当てるための経験則を探していました。 SOに関する多くの議論をここで見つけました。多くの人が言った、それはオブジェクトの寿命についてです。関数のスコープよりも長いライフタイムが必要な場合は、ヒープに入れてください。それは完全に理にかなっています。
しかし、私を混乱させたのは、オブジェクトが小さい場合にスタックにオブジェクトを割り当てることです。オブジェクトが大きい場合は、ヒープに配置します。しかし、彼らは誰もオブジェクトを識別する方法が大きいかどうかを言いませんでしたか?
次の質問があります
- オブジェクトを識別する方法が大きいかどうか
- スタックの最大サイズはいくらですか?各OSのスタックサイズは異なりますか?
-
vector<string>
をラップするラッパークラスがあります。約100個のアイテムがあります。このクラスをスタックに割り当てると、スタックオーバーフローが発生しますか?これを試しましたが、完全に機能しました。私が何か間違ったことをしているのかどうかわかりません。
解決
まず、ベクトル(およびすべてのSTLコンテナクラス)は常にヒープから割り当てられるため、そのことを心配する必要はありません。可変サイズのコンテナの場合、スタックを使用することはほとんど不可能です。
スタック割り当てがどのように機能するかを考える場合(コンパイル時に、基本的に各オブジェクトのポインタをインクリメントすることにより)、ベクトルメモリがヒープから来ることは明らかです。
std::vector<int> myInts;
std::string myString;
SomeOther Class;
// this memory must come from the heap, there's no way it
// can now be allocated on the stack since there are other
// objects and these parameters could be variable
myString = "Some String";
myInts.reserve(256);
再帰関数を使用している場合を除き、スタックに数キロバイトのデータをそれほど心配なく配置できます。スタックサイズは(OSではなく)プログラムによって制御され、デフォルトは32kb-1mbの範囲です。ほとんどのデスクトップソフトウェアは1 MBの範囲で提供されます。
個々のオブジェクトはほとんど問題になりません。一般に、それらはスタックに十分小さいか、またはヒープから内部的に割り当てられます。
オブジェクトが関数に対してローカルである場合、それらをスタックに配置します。ヒープに配置しない場合。
データのロード/ソート/操作に割り当てる大きなバッファにヒープを使用します。
他のヒント
MSDN スタックサイズのデフォルト1MBまで(これは明らかにMsdev向けです。)
記事からわかるように、/ Fフラグを使用してコンパイル時にスタックサイズを変更できます。
一時的なスコープ変数がmbよりも大きい場合、それをヒープに固定するという条件で、スタックとヒープの使用に関する最初のガイドラインはかなり正確だと思います最初の短い期間)。
スタックに大きなオブジェクトを割り当てることができる唯一の方法は、ある時点で古いスタイルの配列を使用することです。例:
void f() {
char a[1000000]; // big object on the stack
}
struct A {
char c[1000000];
};
void g() {
A a; // another big object on the stack
}
配列を使用しない場合(使用すべきではありません)、ヒープ上でほとんどのものが割り当てられます:
void h() {
std::string s( 100000 );
}
上記は、ポインター、サイズ情報などのためにスタック上に数バイトを割り当て、ヒープ上の実際のストレージを割り当てます。
だから心配しないでください!あなたはおそらく正しいことをしています!
オブジェクトを識別する方法は大きいかどうか
コンパイラ/プラットフォームのコンボに依存します。 One Trueの制限はありません。コンパイラでは、多くの場合、これを調整できます。
スタックの最大サイズはどうなりますか?各OSのスタックサイズは異なりますか?
主に上記に依存します。チューニングの制御がほとんどできないもの。
ベクターをラップするラッパークラスがあります。約100個のアイテムがあります。このクラスをスタックに割り当てると、スタックオーバーフローが発生しますか?これを試しましたが、完全に機能しました。何か間違ったことをしているのかわかりません。
このラッパーとそのブロック内の他のオブジェクトの合計メモリ要件がスタックフレームサイズを超えない限り機能します。これは、平均的な文字列に依存します。
良いアイデアは、デバッガーをステップスルーしてスタックアドレスを確認することです。これにより、ある程度の幅の開始が得られます。そしてドキュメント。
1。オブジェクトを識別する方法は大きいかどうか
<!> quot; sizeof <!> quot;
を使用class c {
std::vector<std::string> s;
};
int size = sizeof(c);
私のマシンでは<!> quot; size <!> quot; 16バイトです。
2。スタックの最大サイズはいくらですか?各OSのスタックサイズは異なりますか
わかりませんが、大量のデータを割り当てるには決して良い場所ではありません。
3。ベクトルをラップするラッパークラスがあります。約100個のアイテムがあります。このクラスをスタックに割り当てると、スタックオーバーフローが発生しますか?これを試しましたが、完全に機能しました。間違ったことをしているのかどうかわかりません。
いいえ。 std :: vectorは、ヒープ内の100個のアイテムを割り当てます。
私が言及するもう1つのポイントは、vector<>
はそれ自体のサイズを変更できる必要があるため、十分に大きくなった場合(以下を参照)、含まれるオブジェクトを格納するためにヒープを使用する必要があることです、 <=>自体がスタック変数として宣言されている場合でも。
[編集] Mottiがコメントで指摘しているように、<=>は、小さなベクトルの最適化として、スタックに割り当てられたオブジェクト内に少量のスペースを予約する可能性があります。その場合、このスペース内に収まるほど小さいベクトルを扱う場合、ヒープの割り当ては必要ありません。 (この事前に割り当てられたスペースは、小さいベクトルで作業するときにスペースを無駄にしないために非常に小さくなければなりません。)それにもかかわらず、ベクトルが十分に大きくなった場合、ヒープに(再)割り当てが必要になります。