15

所以istringstream在初始化时复制字符串的内容,例如

string moo("one two three four");
istringstream iss(moo.c_str());

我想知道是否有一种方法可以在不复制内容的情况下std::istringstream使用给定的缓冲区。c_str这样,它就不必在将 传递给作为参数的std::istringstream&函数之前复制大量内存。istream&

我一直在尝试做的是将一些只接受std::ifstream&参数(它们主要是解析器)的函数也转换为接受istream&。我必须为此创建自己的istream子类吗?

4

5 回答 5

9

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

先前的答案表明 deprecated istrstream,但是由于这会产生警告并且将来可能会被删除,因此更好的解决方案是使用boost::iostreams

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

这避免了以相同的方式复制缓冲区istrstream,并且不必编写自己的流类。

于 2016-06-08T21:02:01.463 回答
5

std::streambuf编写一个从给定内存区域读取的基本类相当简单。然后,您可以从中构造一个istream并从中读取。

从内存缓冲区初始化 C++ std::istringstream?

请注意,指向的缓冲区的生命周期c_str()非常有限,并且不能保证调用c_str()want 会导致一些复制,尽管我不知道它的任何实现。

于 2010-06-26T09:21:45.813 回答
3

已弃用的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_
}
于 2010-06-26T09:03:42.267 回答
2

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

只需传入而string无需调用c_str()

istringstream iss(moo);

好吧,这并不能完全阻止复制,但它消除了不必要的复制。要完全消除副本,您必须重写std::stringbuf,这特别避免直接在string您提供的内容上工作。

于 2010-06-26T06:36:33.697 回答
2

这取决于 std::string 的作用。根据 27.2.1/1 The class basic_istringstream<charT,traits,Allocator> ... uses a basic_stringbuf<charT,traits,Allocator> object to control the associated storage. ,由于类必须使用对象,因此必须将字符串复制到该对象中。

所以真正的问题不是 astringstream是否复制内容,而是复制构造字符串是否会复制内容或实现某种写时复制方案。

于 2010-06-26T06:46:07.217 回答