13

私は次のコードを持っています

std::vector<std::string> lines;
std::string currentLine;

while(std::getline(std::cin, currentLine)) {
  // // option 1
  // lines.push_back(std::move(currentLine));

  // // option 2
  // lines.push_back(currentLine);
}

2つのコストが異なると思います

  1. 最初のアプローチはクリアされcurrentLinegetline文字列に新しいバッファを割り当てる必要があります。ただし、代わりにベクターのバッファーを使用します。

  2. 2番目のアプローチではgetline、バッファーを再利用できるようになり、ベクトル内文字列に新しいバッファー割り当てが必要になります。

そのような状況では、「より良い」方法はありますか?コンパイラーは、1つまたは他のアプローチをより効率的に最適化できますか?または、一方のオプションをもう一方のオプションよりもはるかにパフォーマンスの高いものにする巧妙な文字列の実装はありますか?

4

1 に答える 1

3

短い文字列の最適化が普及していることを考えると、多くの場合、これはまったく違いがないということです。SSOを使用すると、移動すると、含まれているデータがコピーされてしまいます(ソースが右辺値であっても、移動のソースとして適格)。

あなたが与えた2つの間で、私は動かないバージョンを好む傾向があると思います、しかしそれがどちらの方法でも大きな違いを生むだろうとは思えません。(ほとんどの場合)移動の直後にソースを再利用することになることを考えると、移動が実際に多くの効果をもたらすとは思えません(せいぜいでも)。SSOが関与していないと仮定すると、読み取りた文字列のコピーを保持するためにベクトルに新しい文字列を作成するか、読み取った文字列から移動して(本質的に)次の行を保持するために新しい文字列を作成することを選択します。次の反復。いずれにせよ、高価な部分(文字列を保持するためのバッファの割り当て、そのバッファへのデータのコピー)は、どちらの方法でもほとんど同じになります。

「もっと良い方法はありますか」という限り、少なくともいくつかの可能性を考えることができます。最も明白なのは、ファイルをメモリマップしてから、そのバッファをウォークスルーし、行の終わりを見つけて、emplace_back中間文字列をまったく使用せずに、バッファ内のデータから直接ベクトルに文字列を作成するために使用することです。

これには、メモリマッピングが標準化されていないという小さな欠点があります。そのレベルの非移植性に耐えられない場合は、メモリマッピングの代わりにファイル全体をバッファに読み込むことができます。

その後の次の可能性は、const文字列のようなインターフェイスを備えたクラスを作成することです。このクラスは、データのコピーを作成する代わりに、データへのポインタを大きなバッファに保持します(たとえば、CLangはこのようなものを使用します)。これにより、通常、合計割り当てやヒープの断片化などが削減されますが、(たとえば)後で文字列を変更する必要がある場合は、(あるとしても)あまり役に立たない可能性があります。

于 2012-08-20T22:54:35.350 に答える