我有一个网络客户端,其中一个请求方法需要传入一个 std::streambuf*
。这个方法是通过将其复制到一个自定义的 std::streambuf
派生类上实现的,该派生类知道如何将数据写入网络API,效果很好。这意味着我可以将文件流式传输到请求中,而无需将其全部读入内存。
然而,有些情况下必须发送大块不在文件中的数据,因此我添加了一个重载函数,以接受字符串作为参数。为了避免在流中重复编写所有网络代码,显然应该设置代表该字符串的streambuf
,并调用其他方法。唯一我能想出来的方法是:
std::istringstream ss(data);
send(ss.rdbuf());
不幸的是,istringstream
会复制数据,而在某些情况下,数据量可能达到几兆字节。当然,在一般情况下,这是有道理的,如果你将一个常量引用交给某个对象,你不希望该对象假设它可以继续使用该引用。
我通过以下方式解决了这个问题:
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 *
参数的函数?有更好的方法来做到这一点吗?
std::stringbuf
派生来设置自定义输入或输出流,并且我只需要覆盖一个或两个简单的函数,即underflow
或overflow
和sync
,基类会为我处理所有缓冲区管理。我怀疑基于std::vector
的东西意味着我需要更多的代码。不过我可能仍然可以使用swap
,尽管我需要让调用者“放弃”字符串而不是传递常量引用。 - Tim Sylvester