10

を受け取るリクエスト メソッドを持つネットワーク クライアントがありますstd::streambuf*。このメソッドは、データをネットワーク API に書き込む方法を知っているboost::iostreams::copyカスタム派生クラスにそれを渡すことによって実装されます。これはうまく機能します。std::streambufこれは、すべてのファイルをメモリに読み込む必要なく、ファイルをリクエストにストリーミングできることを意味します。

ただし、ファイルにない大きなデータ ブロックを送信する必要がある場合もあるため、文字列を受け取るオーバーロードを含めました。ストリーム内のすべてのネットワーク コードが重複しないようにするには、文字列を表す を設定してstreambuf、別のメソッドを呼び出す必要があることは明らかです。これを機能させるために私が見つけた唯一の方法は、次のようなものでした。

std::istringstream ss(data);
send(ss.rdbuf());

残念ながら、istringstream場合によっては数メガバイトのデータのコピーを作成します。もちろん、一般的なケースでは完全に理にかなっています。あるオブジェクトへの const 参照を渡す場合、そのオブジェクトがその参照を引き続き使用できると仮定して、そのオブジェクトを望まない場合です。

私はこれを次のように回避しました:

struct zerocopy_istringbuf
    : public std::stringbuf
{
    zerocopy_istringbuf(std::string const* s)
        : std::stringbuf(std::ios::in)
    {
        char* p = const_cast<char*>(s->c_str());
        setg(p, p, p + s->length());
    }
};

...

send(&zerocopy_istringbuf(data));

これはうまく機能しているように見えますが、本当に必要なのだろうか。std::istringstreamを受け取るオーバーロードがないのはなぜstd::string const *ですか? これを行うより良い方法はありますか?

4

2 に答える 2

4

これらの問題が発生している理由は、std::stringが実際に行っていることに適していないためです。より良いアイデアは、生データを渡すときにcharのベクトルを使用することです。可能であれば、vector :: swapとベクトルへの参照を適切に使用して、すべてのコピーを排除するように、すべてを変更してvectorを使用します。iostreams / streambuf apiが好きな場合、またはstreambufを使用するものを処理する必要がある場合は、自分のようなベクトルを使用する独自のstreambufを作成するのは簡単です。他の回答に記載されているのと同じ問題で行うのと同じことを効果的に行いますが、クラスの契約に違反することはありません。

そうでなければ、私はあなたが持っているものはおそらくどこでもistringstreamを回る以外に前進するための最良の方法だと思います。

于 2009-10-19T18:13:51.020 に答える
2

私見、最良の選択は非推奨のクラス std::strstream です

于 2010-07-07T23:28:16.440 に答える