1. ホーム
  2. c++

[解決済み] C++による効率的な文字列の連結

2022-05-16 02:44:14

質問

std::string の "+" 演算子について心配している人や、連結を高速化するための様々な回避策を聞いたことがあります。これらのうちどれかが本当に必要なのでしょうか? もしそうなら、C++ で文字列を連結する最良の方法は何でしょうか?

どのように解決するのですか?

余分な作業は、あなたが本当に本当に効率を必要としない限り、おそらく価値がありません。 おそらく、代わりに演算子 += を使用するだけで、はるかに良い効率を得ることができます。

さて、この免責事項の後、私はあなたの実際の質問に答えます...

STL文字列クラスの効率は、使用しているSTLの実装に依存します。

あなたは 効率を保証する より大きな制御ができる を自分でコントロールできるようになります。

なぜoperator+は効率的でないのか。

このインターフェイスを見てください。

template <class charT, class traits, class Alloc>
basic_string<charT, traits, Alloc>
operator+(const basic_string<charT, traits, Alloc>& s1,
          const basic_string<charT, traits, Alloc>& s2)

各+の後に新しいオブジェクトが返されているのがわかると思います。これは、毎回新しいバッファが使われることを意味します。 もし余分な+操作を大量に行うのであれば、それは効率的ではありません。

より効率的にできる理由

  • デリゲートを信頼して効率的にやってもらうのではなく、効率を保証することになる
  • std::string クラスは文字列の最大サイズについて何も知りませんし、どれくらいの頻度で文字列を連結するのかも知りません。 あなたはこの知識を持っていて、この情報に基づいて物事を行うことができます。 これは再割り当てを減らすことにつながります。
  • バッファを手動で制御することになるので、そうしたくないときに文字列全体を新しいバッファにコピーすることがないことを確認できます。
  • ヒープの代わりにバッファにスタックを使用することができ、より効率的です。
  • string + 演算子は新しい文字列オブジェクトを作成し、それを返すので、新しいバッファを使用します。

実装のための考慮点。

  • 文字列の長さを記録する。
  • 文字列の終端と開始へのポインタを保持するか、開始だけを保持し、開始+長さをオフセットとして使用して文字列の終端を見つけます。
  • 文字列を格納するバッファが十分に大きいことを確認し、データを再割り当てする必要がないようにする。
  • strcatの代わりにstrcpyを使用し、文字列の終わりを見つけるために文字列の長さを繰り返し処理する必要がないようにします。

ロープのデータ構造です。

もし、本当に高速な連結が必要な場合は ロープデータ構造 .