【问题标题】:How to reuse an ostringstream?如何重用 ostringstream?
【发布时间】:2010-10-12 01:48:54
【问题描述】:

我想清除并重用一个 ostringstream(和底层缓冲区),这样我的应用就不必进行那么多分配。如何将对象重置为其初始状态?

【问题讨论】:

标签: c++ stl reset ostringstream


【解决方案1】:

我过去使用过 clear 和 str 的序列:

// clear, because eof or other bits may be still set. 
s.clear();
s.str("");

这对输入和输出字符串流都做了这件事。或者,您可以手动清除,然后寻找适当的顺序开始:

s.clear();
s.seekp(0); // for outputs: seek put ptr to start
s.seekg(0); // for inputs: seek get ptr to start

这将通过覆盖当前输出缓冲区中的任何内容来防止str 完成的某些重新分配。结果是这样的:

std::ostringstream s;
s << "hello";
s.seekp(0);
s << "b";
assert(s.str() == "bello");

如果你想将字符串用于 c 函数,你可以使用std::ends,像这样放置一个终止 null:

std::ostringstream s;
s << "hello";
s.seekp(0);
s << "b" << std::ends;
assert(s.str().size() == 5 && std::strlen(s.str().data()) == 1);

std::ends 是已弃用的std::strstream 的遗留物,它能够直接写入您在堆栈上分配的字符数组。您必须手动插入终止空值。但是,std::ends 并未被弃用,我认为因为它在上述情况下仍然有用。

【讨论】:

  • 我正在尝试将 s.str() 与 ostream 一起使用。大小搞砸了(我可以看到第一个字符为空,但它打印的更多)。有没有固定str长度的好方法?我正在使用 s.str().c_str(); ATM,它工作得很好
  • 其实这也不对。我只是做了s.str("");。 auto str = s.str(); auto cstr = str.c_str(); file &lt;&lt; cstr; s.clear(); s.seekp(0); s &lt;&lt; ends;
  • std::ends 在谷歌测试中对我不起作用 boost::any a = 1; std::ostringstream buffer; buffer &lt;&lt; a &lt;&lt; std::ends; EXPECT_EQ( buffer.str(), "any&lt;(int)1&gt;" ); TestUtilsTest.cpp:27: Failure Expected: buffer.str() Which is: "any&lt;(int)1&gt;\0" To be equal to: "any&lt;(int)1&gt;" 如果我使用不同长度的字符串重复使用,我会留下位
  • 如果您想避免重新分配,替代方案是真正的答案。如果你想在不重新分配的情况下真正“重新开始”,只需在发送 std::end 后再次调用 seekp(0)。 s.seekp(0); s &lt;&lt; std::ends; s.seekp(0);
【解决方案2】:

似乎ostr.str("") 调用可以解决问题。

【讨论】:

  • 值得指出的是,这不会重用来自 ostringstream 的底层缓冲区 - 它只是分配一个新缓冲区。因此,当您重用 ostringstream 对象时,您仍在分配两个缓冲区。我不认为 ostringstream 旨在以您想要的方式重用。
  • 它也不会清除状态,这就是 .clear() 所做的。我同意,它真的不适合这样使用。只需创建一个新的即可。只有当您进行分析时,您才会发现它是否有任何不同。
  • sgreeve,布赖恩,没错。但是请注意,上述 litb 的方法如何要求使用 std::ends。它重用了缓冲区,但让您使用 stringstreams 编写不同的代码(通常您不使用 std::ends)。
【解决方案3】:

如果您要清除缓冲区以使其在第一次使用之前被清除,您需要先使用 MSVC 向缓冲区添加一些内容。

struct Foo {
    std::ostringstream d_str;
    Foo() { 
        d_str << std::ends;   // Add this
    }
    void StrFunc(const char *);
    template<class T>
    inline void StrIt(const T &value) {
        d_str.clear();
        d_str.seekp(0);  // Or else you'll get an error with this seek
        d_str << value << std::ends;
        StrFunc(d_str.str().c_str());  // And your string will be empty
    }
};

【讨论】:

  • 我没有看到 VS2012 上的失败行为。此外,如果流为空,调用clear 将导致设置failbit。虽然只是调用seekp,但如果不存在流,则应该简单地返回。
【解决方案4】:

你没有。为了清楚起见,使用两个不同命名的流,并让优化编译器确定它可以重用旧的流。

【讨论】:

  • 考虑代码循环输入数据的用例,写入ostringstream(基于读取的数据),然后必须不时写入ostringstream中内置的字符串到时间(例如在读取某个字符序列之后)并开始构建一个新字符串。
猜你喜欢
  • 2011-07-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-24
  • 1970-01-01
相关资源
最近更新 更多