3

unsigned charnull ターミネータのないさまざまな固定サイズの配列を文字列として使用する C ライブラリを使用しています。

私はstd::string次の関数を使用してそれらを変換しています:

auto uchar_to_stdstring(const unsigned char* input_array, int width) -> std::string {
  std::string temp_string(reinterpret_cast<const char*>(input_array), width);
  temp_string.erase(temp_string.find_last_not_of(' ') + 1);

  return temp_string;
}

reinterpret_castの使用、配列サイズを渡す必要性、および配列をポインターに減衰させているという事実を除いて、これはうまく機能します。を使用して、これらの問題をすべて回避しようとしていますstd::span

使用する関数はstd::span次のようになります。

auto ucharspan_to_stdstring(const std::span<unsigned char>& input_array) -> std::string {
  std::stringstream temp_ss;

  for (const auto& input_arr_char : input_array) {
    temp_ss << input_arr_char;
  }

  return temp_ss.str();
}

この関数はうまく機能し、C 配列のサイズを追跡する必要がなく、他のすべてがより簡単になります。しかし、いくつかのベンチマーク ( nanobenchreinterpret_castを使用) でさらに掘り下げると、新しい関数は従来の方法よりも何倍も遅いことがわかります。私の仮定は、ベース関数のforループがここで非効率的であるということです。std::span

私の質問:std::span unsigned char の固定サイズの C 配列を変数からに変換するより効率的な方法はありstd::stringますか?


編集:

gccベンチマーク (-O3 -DNDEBUG -std=gnu++20、ナノベンチ、minEpochIterations=54552558、ウォームアップ=100、doNotOptimizeAway)

相対的 ns/op オペレーション エラー% イン/オペレーション ブラ/手術 お嬢% 合計 uchar[] を std::string に
100.0% 5.39 185,410,438.12 0.3% 80.00 20.00 0.0% 3.56 uchar
2.1% 253.06 3,951,678.30 0.6% 4,445.00 768.00 0.0% 167.74 ucharspan
1,244.0% 0.43 2,306,562,499.69 0.2% 9.00 1.00 0.0% 0.29 ucharspan_barry
72.8% 7.41 134,914,127.56 1.3% 99.00 22.00 0.0% 4.89 uchar_bsv

clangベンチマーク (-O3 -DNDEBUG -std=gnu++20、ナノベンチ、minEpochIterations=54552558、ウォームアップ=100、doNotOptimizeAway)

相対的 ns/op オペレーション エラー% イン/オペレーション ブラ/手術 お嬢% 合計 uchar[] を std::string に
100.0% 2.13 468,495,014.11 0.2% 14.00 1.00 0.0% 1.42 uchar
0.8% 251.74 3,972,418.54 0.2% 4,477.00 767.00 0.0% 166.30 ucharspan
144.4% 1.48 676,329,668.07 0.1% 7.00 0.00 95.8% 0.98 ucharspan_barry
34.5% 6.19 161,592,563.70 0.1% 80.00 24.00 0.0% 4.08 uchar_bsv

(uchar_bsvベンチマークでは と同じですが、ucharspan_barry代わりstd::basic_string_view<unsigned char const>にパラメーターがありますstd::span<unsigned char const>

4

1 に答える 1