1. ホーム
  2. c++

[解決済み】std::string_viewはconst std::string& よりも具体的にどのように速いのでしょうか?

2022-03-31 01:47:12

質問

std::string_view は C++17 で採用され、その代わりにこれを使用することが広く推奨されています。 const std::string& .

その理由のひとつは、パフォーマンスです。

どなたか、どのように まさに std::string_view よりも高速になります。 const std::string& をパラメータ型として使用した場合、どのようになりますか?(仮にcalleeのコピーが作られないとします)

解決方法は?

std::string_view の方が速い場合があります。

まず std::string const& にはデータが必要です。 std::string であり、C言語の生の配列ではなく char const* は、C言語のAPIから返される std::vector<char> デシリアライゼーションエンジンなどで生成されます。 フォーマット変換を避けることで、バイトのコピーを回避し、(もし文字列が、特定の std::string を実装することで、メモリの割り当てを回避することができます。

void foo( std::string_view bob ) {
  std::cout << bob << "\n";
}
int main(int argc, char const*const* argv) {
  foo( "This is a string long enough to avoid the std::string SBO" );
  if (argc > 1)
    foo( argv[1] );
}

での割り当ては行われません。 string_view の場合ですが、もし foo を取った。 std::string const& の代わりに string_view .

2つ目の大きな理由は、部分文字列をコピーせずに処理できることです。 例えば、2ギガバイトのjson文字列(!)をパースしているとします²。 これをパースして std::string の名前または値を格納するようなパースノードがあります。 コピー 2gbの文字列の元データをローカルノードにコピーする。

その代わり、パースして std::string_view の場合、ノード 参照 を元データに変換します。 これにより、何百万ものアロケーションを節約し、パース時のメモリ要件を半減させることができます。

得られるスピードアップは、まさにバカバカしいほどです。

これは極端なケースですが、他のquot;部分文字列を取得してそれを処理する"ケースでも、以下のように適切な速度が得られます。 string_view .

を使うことで何を失うのかが判断の重要なポイントになります。 std::string_view . それは大したことではありませんが、何かあるのです。

暗黙のNULL終端を失いますが、それくらいです。 つまり、同じ文字列が3つの関数に渡され、そのすべてがNULL終端を必要とする場合、以下のように変換されます。 std::string を一回で済ませるのが賢明かもしれません。 したがって、もしあなたのコードがヌルターミネータを必要とすることが分かっていて、Cスタイルのソースバッファなどから供給される文字列を期待しないのであれば、おそらく std::string const& . そうでない場合は std::string_view .

もし std::string_view を使用する最後の理由さえも取り除くことができます。 std::string const& .

を取るケースがあります。 std::string がない状態で const& が最適なのは std::string_view . 呼び出しの後、無期限に文字列のコピーを所有する必要がある場合、by-valueを取ることが効率的です。 SBOの場合(そして、アロケーションもなく、数文字のコピーで複製するだけ)か、あるいは 移動 ヒープで確保されたバッファをローカルの std::string . 2つのオーバーロードを持つ std::string&&std::string_view は速くなるかもしれませんが、ほんのわずかであり、コードの肥大化(スピードアップをすべて失う可能性があります)を引き起こします。


¹ スモールバッファの最適化

² 実際の使用例