我有一个名为std::string
的对象,希望通过std::ostream
接口填充数据,避免字符串复制。
其中一种涉及副本的方法是这样做:
bool f(std::string& out)
{
std::ostringstream ostr;
fillWithData(ostr);
out = ostr.str(); // 2 copies here
return true;
}
我需要通过out
传递结果,并且不能 * 返回 * ostr.str()
。
我想避免out = ostr.str();
中的副本,因为这个字符串可能非常大。
是否有某种方法,比如使用rdbuf()
s,将std::ostream
缓冲区直接绑定到out
?
澄清一下,我对std::string
和std::ostream
的自动扩展行为很感兴趣,这样调用者就不必在调用之前知道大小。
更新:我刚刚意识到无害行out = ostr.str();
可能需要2个副本:
1.第一个由str()
调用
1.另一个由std::string
赋值运算符执行。
3条答案
按热度按时间qco9c6ql1#
编写您自己的流:
注意:您可以在一个更复杂的实现中管理put区域指针。
olqngx592#
这是我从https://stackoverflow.com/a/51571896/577234中定制的流缓冲区解决方案。它比Dieter的要短得多--只需要实现overflow()。它还通过设置缓冲区来提高重复ostream::put()的性能。使用ostream::write()进行大型写入的性能将是相同的,因为它调用xsputn()而不是overflow()。
他们说一个好的程序员是一个懒惰的人,所以这里是我想出的一个替代实现,它需要更少的自定义代码。然而,有内存泄漏的风险,因为它劫持了MyStringBuffer内部的缓冲区,但没有释放MyStringBuffer。在实践中,它不会泄漏GCC的streambuf,我使用AddressSanitizer确认了这一点。
rryofs0p3#
没有第二个副本,因为它是移动分配。
从C++20开始,
std::ostringstream
提供了一个新的成员函数,它可以消耗自身并返回std::string
:因此,您可以通过以下方式避免第一个副本:
参考文献
https://en.cppreference.com/w/cpp/io/basic_ostringstream/str