非复制字符串流

发布于 2024-09-07 20:06:08 字数 442 浏览 7 评论 0原文

因此,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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

洋洋洒洒 2024-09-14 20:06:08

使用 istringstream 并不是一个令人满意的解决方案,因为这会复制整个缓冲区。

之前的答案建议使用已弃用的 istrstream,但由于这会生成警告并且将来可能会被删除,因此更好的解决方案是使用 boost::iostreams

boost::iostreams::stream<boost::iostreams::array_source> stream(moo.c_str(), moo.size());

这避免了以 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:

boost::iostreams::stream<boost::iostreams::array_source> stream(moo.c_str(), moo.size());

This avoids copying the buffer in the same way istrstream did, and saves you having to write your own stream class.

羁客 2024-09-14 20:06:08

编写一个从给定内存区域读取的基本 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 an istream 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 to c_str() want cause some copying although I don't know of any implementations where it does.

野鹿林 2024-09-14 20:06:08

已弃用的 istrstream 支持此功能。

#include <string>
#include <strstream>
using namespace std;

int main(int argc, char* argv[])
{
    string moo = "one two three four";
    istrstream istr(const_cast<char*>(moo.c_str()),moo.size());
    std::string line;
    while(!istr.fail() && !istr.eof()){
        getline(istr,line,' ');
        cout << line << "_";
    }
    // prints: one_two_three_four_
}

the deprecated istrstream supports this feature.

#include <string>
#include <strstream>
using namespace std;

int main(int argc, char* argv[])
{
    string moo = "one two three four";
    istrstream istr(const_cast<char*>(moo.c_str()),moo.size());
    std::string line;
    while(!istr.fail() && !istr.eof()){
        getline(istr,line,' ');
        cout << line << "_";
    }
    // prints: one_two_three_four_
}
我恋#小黄人 2024-09-14 20:06:08

只有一个副本,因为您传递的参数 const char* 需要转换为 istringstream 构造函数

只需传入字符串,而不调用c_str()

istringstream iss(moo);

好吧,这并不能完全阻止复制,但它消除了不必要的复制。要完全消除副本,您必须重写 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 calling c_str().

istringstream iss(moo);

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 the string you give it.

愿得七秒忆 2024-09-14 20:06:08

这取决于 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.

溺ぐ爱和你が 2024-09-14 20:06:08

经过几天的搜索和尝试各种方法包括scnlib、sscanf、istingstream等,也许我找到了答案。如果您关心解析性能,则应该使用 charsconv 标头已添加到 C++17。这是在 C++ 中快速解析 string_view 的唯一合理解决方案。

根据 cppreference

与 C++ 和 C 库中的其他解析函数不同,std::from_chars 与语言环境无关、不分配且不抛出异常。仅提供其他库(例如 std::sscanf)使用的一小部分解析策略。这样做的目的是允许以最快的速度实现,这在常见的高吞吐量上下文中非常有用,例如基于文本的交换(JSON 或 XML)。

其他方法的问题如下:

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 of string_view in C++.

According to cppreference:

Unlike other parsing functions in C++ and C libraries, std::from_chars is locale-independent, non-allocating, and non-throwing. Only a small subset of parsing policies used by other libraries (such as std::sscanf) is provided. This is intended to allow the fastest possible implementation that is useful in common high-throughput contexts such as text-based interchange (JSON or XML).

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文