10

インスタンス間でデータを効率的にコピーしたいと考えています。std::streambufつまり、文字ごとのコピーを実行するのではなく、それらの間でデータのブロックをシャベルで処理したいと考えています。たとえば、これは私が探しているものではありません。

stringbuf in{ios_base::in};
stringbuf out{ios_base::out};
copy(istreambuf_iterator<char>{in},
     istreambuf_iterator<char>{},
     ostreambuf_iterator<char>{out});

これには構文糖衣があり、もう少しエラーチェックが行われます:

ostream os{&out};
os << &in;

operator<<(basic_streambuf<..>*)これは、私の標準ライブラリ (Mac OS X、XCode 7)での実装のスニペットです。

                typedef istreambuf_iterator<_CharT, _Traits> _Ip;
                typedef ostreambuf_iterator<_CharT, _Traits> _Op;
                _Ip __i(__sb);
                _Ip __eof;
                _Op __o(*this);
                size_t __c = 0;
                for (; __i != __eof; ++__i, ++__o, ++__c)
                {
                    *__o = *__i;
                    if (__o.failed())
                        break;
                }

要するに、これはまだ文字ごとのコピーです。標準ライブラリが、文字ごとのトランスポートとは対照的に、sputnストリームバッファのブロック レベルのメンバー関数に依存するアルゴリズムを使用することを期待していました。sgetn標準ライブラリはそのようなアルゴリズムを提供していますか、それとも自分で作成する必要がありますか?

4

1 に答える 1

2

残念ながら、現在の標準ライブラリの設計では不可能です。その理由は、ストリームバッファが管理する文字シーケンスを完全に隠すためです。これにより、あるストリームバッファの get 領域から別のストリームバッファの put 領域にバイトを直接コピーすることができなくなります。

「入力」ストリームバッファが内部バッファを公開する場合、「出力」ストリームバッファはsputn(in.data(), in.size()). またはもっと明らかに: 出力バッファも内部バッファを公開している場合、プレーンを使用memcpyして 2 つの間でバイトをシャベルできます。他の I/O ライブラリは、この方法で動作します。たとえば、Google のプロトコル バッファのストリーム実装です。Boost IOStreams には、ストリーム間でコピーするための最適化された実装があります。どちらの場合も、ストリームバッファの等価物がその中間バッファへのアクセスを提供するため、効率的なブロックレベルのコピーが可能です。

実際、ストリームバッファは皮肉なことにバッファを持つ必要さえありません。バッファなしで動作する場合、各読み取り/書き込みは下層のデバイスに直接行きます。おそらくこれが、標準ライブラリがイントロスペクションをサポートしていない理由の 1 つです。残念なことに、入力ストリームバッファと出力ストリームバッファの間で効率的なコピーを行うことはできません。ブロック レベルのコピーには中間バッファーが必要であり、コピー アルゴリズムは次のように動作します。

  1. 入力ストリームsgetnバッファから中間バッファに読み込みます。
  2. 経由で中間バッファから出力ストリームバッファに書き込みsputnます。
  3. 入力が使い果たされるか、出力ストリームバッファへの書き込みが失敗するまで、1.に進みます
于 2016-05-29T04:57:48.763 に答える