29

std::stringstreamは自分のアプリケーションで文字列とエラー メッセージを作成するために広く使用しています。stringstreams通常、自動変数は非常に短い寿命です。

このような使用法は、すべての変数に対してヒープの再割り当てを引き起こしますか? 一時変数からクラスメンバーstringstream変数に切り替える必要がありますか?

後者の場合、どうすればstringstreamバッファを予約できますか? (十分な大きさの文字列で初期化する必要がありますか、それとももっと洗練された方法がありますか?)

4

4 に答える 4

10

実行のプロファイルを作成し、それらが速度低下の原因であることがわかりましたか?

それらの使用法を検討してください。それらは主に、コードの通常のフロー外のエラーメッセージ用ですか?

スペースの予約に関しては...

一部の実装では、文字列ストリームの割り当てが行われる前に、おそらく小さなバッファが予約されています。std::stringの多くの実装はこれを行います。

別のオプションは(テストされていない!)かもしれません

std::string str;
str.reserve(50);
std::stringstream sstr(str);

このgamedevスレッドでさらにいくつかのアイデアを見つけることができます。

編集:

stringstreamのrdbufをいじくり回すことも解決策かもしれません。このアプローチはおそらく間違いを犯しやすいので、絶対に必要であることを確認してください。確かにエレガントでも簡潔でもありません。

于 2009-12-21T16:33:07.553 に答える
2

悪い人

これは古い質問ですが、C++1z/C++2a の時点でもVisual Studio 2019stringstreamバッファを予約する理想的な方法はありません。

この質問に対する他の回答は、次の理由によりまったく機能しません。

  • 空の文字列で reserve を呼び出すと空の文字列が生成されるため、stringstreamコンストラクターはその文字列の内容をコピーするために割り当てる必要はありません。

  • seekpstringstreamまだ未定義の動作のようであり、および/または何もしません。

いいもの

このコード セグメントssは、要求されたサイズで事前に割り当てられているため、期待どおりに機能します。

std::string dummy(reserve, '\0');
std::stringstream ss(dummy);
dummy.clear();
dummy.shrink_to_fit();

コードはワンライナーとして書くこともできますstd::stringstream ss(std::string(reserve, '\0'));

ぶさいく

このコード セグメントで実際に行われることは次のとおりです。

  • dummyリザーブが事前に割り当てられ、その後、バッファは null バイトで埋められます (コンストラクタに必要)。
  • stringstreamダミーで構成されています。これにより、文字列の内容全体が、事前に割り当てられた内部バッファーにコピーされます。
  • dummyその後、クリアされてから消去され、その割り当てが解放されます。

これは、 a を事前に割り当てるためにstringstream、2 つの割り当て、1 つのフィル、1 つのコピーが行われることを意味します。最悪の部分は、式の実行中に、目的の割り当てに 2 倍のメモリが必要になることです。うわぁ!

ほとんどのユースケースでは、これはまったく問題にならない可能性があり、追加のフィルとコピー ヒットを使用して再割り当てを少なくしても問題ありません。

于 2019-11-22T07:01:28.667 に答える
2

よくわかりませんが、stringbufofstringstreamが results と密接に関連していると思われstringます。したがって、基になるの内部のバイト数ss.seekp(reserved-1); ss.put('\0');を予約するために使用できると思います。実際には のようなものを見たいのですが、ストリームのメソッドはありません。reservedstringssss.seekp(reserved); ss.trunc();trunc()

于 2013-01-02T23:28:49.950 に答える