【问题标题】:non-copying istringstream非复制字符串流
【发布时间】:2011-03-08 13:33:23
【问题描述】:

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

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

我想知道是否有办法让std::istringstream 使用给定的c_str 作为它的缓冲区而不复制东西。这样,它就不必在将std::istringstream& 传递给以istream& 作为参数的函数之前复制大量内存。

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

【问题讨论】:

  • 查看this answer 的方法(与@Charles 的解决方案基本相同,但为方便起见将istream 包裹起来)。

标签: c++ istream istringstream


【解决方案1】:

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

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

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

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

【讨论】:

    【解决方案2】:

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

    initializing a C++ std::istringstream from an in memory buffer?

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

    【讨论】:

    • 啊,谢谢,会试试看。它看起来比我想象的要简单得多:)
    • 在我的情况下,这绝对与istringstream 不同,@Riot bellow 的解决方案确实可以按预期工作。在我的情况下,代码更新在使用seekg 读取时获取 istringstream 中的指针。换句话说,正确的解决方案还需要 seekpos 重载以匹配 ostreingstream 的行为
    【解决方案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_
    }
    

    【讨论】:

    • @sbi:我的错,我先用 strstream 做了一些测试,是剩下的,现在已经修好了。
    【解决方案4】:

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

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

    istringstream iss(moo);
    

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

    【讨论】:

      【解决方案5】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-08-29
        • 2021-07-18
        • 2011-05-22
        • 2017-06-12
        • 2021-09-15
        相关资源
        最近更新 更多