std :: stringstream与直接输出缓冲区/字符串结果访问,避免复制?

时间:2014-02-27 19:33:36

标签: c++ stl iostream stringstream

是否存在std::stringstream的规范/公开/免费实施变体,每次拨打str()时,我都不会为完整的字符串副本付费? (可能通过在骨骼类中提供直接c_str()成员?)

我在这里发现了两个问题:

并且“当然”已弃用的std::strstream类允许直接缓冲区访问,尽管它的界面非常古怪(除了它被弃用)。

似乎人们可以找到several代码samples来解释如何自定义std::streambuf以允许直接访问缓冲区 - 我在实践中没有尝试过,但似乎很容易实现。

我的问题这里真的有两个方面:

  • 是否有更深层次的原因std::[o]stringstream(或者更确切地说,basic_stringbuf不允许直接缓冲区访问,但只能通过(昂贵的)副本访问整个缓冲区?
  • 鉴于它似乎很容易,但并非琐碎来实现这一点,是否有任何通过boost或其他来源提供的varaint,包装此功能?

注意:str()制作的副本的性能损失非常可衡量(*),因此当用例 I时必须为此付费似乎很奇怪到目前为止看到从不需要从stringstream返回的副本。 (如果我需要副本,我总是可以在“客户端”进行。)


(*):使用我们的平台(VS 2005),我在发布版本中测量的结果是:

// tested in a tight loop:

// variant stream: run time : 100%
std::stringstream msg;
msg << "Error " << GetDetailedErrorMsg() << " while testing!";
DoLogErrorMsg(msg.str().c_str());

// variant string: run time: *** 60% ***
std::string msg;
((msg += "Error ") += GetDetailedErrorMsg()) += " while testing!";
DoLogErrorMsg(msg.c_str());

所以使用带有std::string的{​​{1}}(显然只有在我不需要自定义/数字格式时才能使用,比流版本快40%,据我所知,这是只是由于+=制作了完整的多余副本。

2 个答案:

答案 0 :(得分:1)

我会尽力回答我的第一颗子弹,

  

是否有更深层次的原因std::ostringstream不允许直接缓冲区访问

查看如何定义streambuf / stringbuf,我们可以看到缓冲区字符序列不是以NULL结尾

据我所知,提供直接只读缓冲区访问的(假设的)const char* std::ostringstream::c_str() const;函数只有在有效缓冲区范围始终为NULL终止时才有意义 - 即(我认为)当sputc始终确保它在插入的字符后插入终止NULL时。

我不认为这本身就是技术上的障碍,但考虑到basic_streambuf界面的复杂性,我完全不确定它是否在所有情况下都是正确的。

答案 1 :(得分:1)

至于第二个子弹

  

鉴于实现这一点似乎很容易,但并非微不足道   通过boost或其他来源提供的任何变体,包装此   功能?

Boost.Iostreams,它甚至包含an example如何使用字符串实现(o)流接收器。

我想出了一个小测试实现来测量它:

#include <string>
#include <boost/iostreams/stream.hpp>
#include <libs/iostreams/example/container_device.hpp> // container_sink

namespace io = boost::iostreams;
namespace ex = boost::iostreams::example;
typedef ex::container_sink<std::wstring> wstring_sink;
struct my_boost_ostr : public io::stream<wstring_sink> {
    typedef io::stream<wstring_sink> BaseT;
    std::wstring result;
    my_boost_ostr() : BaseT(result)
    { }

    // Note: This is non-const for flush.
    // Suboptimal, but OK for this test.
    const wchar_t* c_str() {
        flush();
        return result.c_str();
    }
};

在我做过的测试中,使用它的c_str()帮助程序运行速度比正常ostringstream略快,并且复制str().c_str()版本。

我不包括测量代码。这方面的表现非常脆弱,请务必亲自测量您的用例! (例如,字符串流的构造函数开销是不可忽略的。)