10

我有一个网络客户端,其请求方法采用std::streambuf*. 该方法是通过boost::iostreams::copy将其添加到自定义std::streambuf派生类来实现的,该类知道如何将数据写入网络 API,效果很好。这意味着我可以将文件流式传输到请求中,而无需将其全部读入内存。

但是,在某些情况下,必须发送不在文件中的大数据块,因此我包含了一个采用字符串的重载。为了避免复制流中的所有网络代码,显然我应该设置一个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超载采取 a std::string const *?有一个更好的方法吗?

4

2 回答 2

4

您遇到这些问题的原因是 std::string 并不真正适合您正在做的事情。一个更好的主意是在传递原始数据时使用 char 向量。如果可能的话,我会改变一切以使用矢量,使用矢量::交换和对矢量的引用作为适当的消除你所有的复制。如果你喜欢 iostreams/streambuf api,或者如果你必须处理需要一个 streambuf 的东西,那么创建你自己的使用向量的 streambuf 将是微不足道的,就像你的一样。它可以有效地做与其他答案中列出的相同问题相同的事情,但您不会违反班级的合同。

否则,我认为您所拥有的可能是最好的前进方式,而不是到处绕过 istringstream。

于 2009-10-19T18:13:51.020 回答
2

恕我直言,最好的选择是不推荐使用的类 std::strstream

于 2010-07-07T23:28:16.440 回答