非复制字符串流
因此,istringstream
在初始化时复制字符串的内容,例如
string moo("one two three four");
istringstream iss(moo.c_str());
我想知道是否有办法使std::istringstream
使用给定的c_str
作为它的缓冲区而不复制东西。这样,在将 std::istringstream&
传递给以 istream&
作为参数的函数之前,就不必复制大量内存。
我一直在尝试做的是将一些仅采用 std::ifstream& 参数的函数(它们主要是解析器)转换为也采用 istream&
。我是否必须为此创建自己的 istream 子类?
So istringstream
copies the contents of a string when initialised, e.g
string moo("one two three four");
istringstream iss(moo.c_str());
I was wondering if there's a way to make std::istringstream
use the given c_str
as its buffer without copying things. This way, it won't have to copy large bits of memory before passing the std::istringstream&
to functions that take istream&
as an argument.
What I've been trying to do is convert some functions which only take std::ifstream&
arguments (they're mostly parsers) into taking istream&
as well. Would I have to make my own istream
subclass for this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
使用 istringstream 并不是一个令人满意的解决方案,因为这会复制整个缓冲区。
之前的答案建议使用已弃用的
istrstream
,但由于这会生成警告并且将来可能会被删除,因此更好的解决方案是使用 boost::iostreams:这避免了以
istrstream
相同的方式复制缓冲区,并保存你必须编写自己的流类。Using
istringstream
is not a satisfactory solution, because this copies the entire buffer.A previous answer suggests the deprecated
istrstream
, but as this generates warnings and may be removed in future, a better solution is to use boost::iostreams:This avoids copying the buffer in the same way
istrstream
did, and saves you having to write your own stream class.编写一个从给定内存区域读取的基本
std::streambuf
类相当简单。然后,您可以从中构造一个istream
并从中读取。从内存缓冲区初始化 C++ std::istringstream ?
请注意,
c_str()
指向的缓冲区的生命周期非常有限,并且不能保证对c_str()
的调用需要导致一些复制,尽管我不知道它的任何实现。It's fairly trivial to write a basic
std::streambuf
class that reads from a given memory area. You can then construct anistream
from this and read from that.initializing a C++ std::istringstream from an in memory buffer?
Note that the lifetime of the buffer pointed to be
c_str()
is very limited, though, and there's no guarantee that a call toc_str()
want cause some copying although I don't know of any implementations where it does.已弃用的
istrstream
支持此功能。the deprecated
istrstream
supports this feature.只有一个副本,因为您传递的参数
const char*
需要转换为 istringstream 构造函数。只需传入
字符串
,而不调用c_str()
。好吧,这并不能完全阻止复制,但它消除了不必要的复制。要完全消除副本,您必须重写
std::stringbuf
,它特别避免直接处理您提供的
字符串
。There's only a copy because the parameter you pass, a
const char*
, requires conversion to the argument type of the istringstream constructor.Just pass in the
string
without callingc_str()
.Well ok, that doesn't prevent copying completely, but it eliminates an unnecessary copy. To completely eliminate the copy, you'd have to rewrite
std::stringbuf
, which specifically avoids working directly on thestring
you give it.这取决于 std::string 的作用。根据27.2.1/1
class basic_istringstream...使用 basic_stringbuf;对象来控制关联的存储。
由于类必须使用对象,因此必须将字符串复制构造到该对象中。因此,真正的问题不是 stringstream 是否复制内容,而是复制构造字符串是否会复制内容或实现某种写时复制方案。
It depends on what a std::string does. According to 27.2.1/1
The class basic_istringstream<charT,traits,Allocator> ... uses a basic_stringbuf<charT,traits,Allocator> object to control the associated storage.
Since the class must use an object it must copy construct the string into that object.So the real question is not whether a
stringstream
copies the contents, but whether copy constructing a string will copy the contents or implement some sort of copy-on-write scheme.经过几天的搜索和尝试各种方法包括scnlib、sscanf、istingstream等,也许我找到了答案。如果您关心解析性能,则应该使用 charsconv 标头已添加到 C++17。这是在 C++ 中快速解析
string_view
的唯一合理解决方案。根据 cppreference:
其他方法的问题如下:
scnlib: 我已经发现它的性能与传入字符串的长度有关,即使您只解析整数,传入长字符串也会导致 线性性能下降。这对于需要高性能的场景来说是不可接受的。
istringstream:正如问题所说,它无法处理范围,并且不可避免地需要在初始化时进行副本。
sscanf: C 风格的空终止字符串是必要的,而根据cppreference。
After a few days of searching and trying various methods including scnlib, sscanf, istringstream, etc., maybe I found the answer. If you care about parsing performance, you should use the
from_chars
family of functions in charsconv header that were added to C++17. This is the only reasonable solution for fast parsing ofstring_view
in C++.According to cppreference:
The problems with the other methods are as follows:
scnlib: I've found that its performance is related to the length of the incoming string, and that even when you're only parsing an integer, passing in a long string causes a linear performance degradation. This is unacceptable for scenarios requiring high performance.
istringstream: As the question says, it can't handle scopes and inevitably requires a copy at initialization time.
sscanf: A C-style null terminated string is necessary, while some implementations may likewise cause performance problems according to cppreference.