У меня есть сетевой клиент с методом запроса, который принимает std::streambuf*
. Этот метод реализован путем boost::iostreams::copy
-переноса его в пользовательский класс, производный от 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 *
? Есть лучший способ сделать это?