从std :: string流而不制作副本?

Tim*_*ter 9 c++ stl stringstream

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

但是,在某些情况下,必须发送不在文件中的大块数据,因此我包含了一个带字符串的重载.为了避免重复流中的所有网络代码,我应该设置一个streambuf代表字符串并调用另一个方法.我能弄清楚这项工作的唯一方法是:

std::istringstream ss(data);
send(ss.rdbuf());
Run Code Online (Sandbox Code Playgroud)

不幸的是,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));
Run Code Online (Sandbox Code Playgroud)

这似乎工作得很好,但我想知道它是否真的有必要.为什么没有std::istringstream过载std::string const *?有一个更好的方法吗?

Dou*_* T. 4

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

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