std :: stringstream与直接输出缓冲区/字符串结果访问,避免复制? [英] std::stringstream with direct output buffer / string result access, avoiding copy?

查看:270
本文介绍了std :: stringstream与直接输出缓冲区/字符串结果访问,避免复制?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否有 std :: stringstream 的规范/公开/免费实施变体,其中我不支付完整的字符串副本时间我调用 str()? (可能通过在osteam类中提供一个直接的 c_str()成员?)



这里:





并且当然已弃用的 std :: strstream 允许对于直接缓冲区访问,虽然它的界面真的很古怪(除了被弃用)。



看起来可以找到几个代码示例解释如何自定义 std :: streambuf 以允许直接访问缓冲区 - 我没有在实践中尝试,但它




  • 是否有任何更深层的原因, std: :[o] stringstream (或者, basic_stringbuf 不允许直接访问缓冲区,但只能通过整个缓冲区的(昂贵的)副本访问

  • 由于这似乎很容易,但实施此操作并不简单,是否有可以通过boost或其他来源打包此功能的任何varaint?



注意: str()的副本的性能影响是非常 ),所以看起来很奇怪,当使用情况到目前为止,真的从来需要一个从stringstream返回的副本。 (如果我需要一个副本,我总是可以在客户端。)






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

  loop:

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

//变体字符串:运行时间:*** 60%***
std :: string msg;
((msg + =Error)+ = GetDetailedErrorMsg())+ =while testing!
DoLogErrorMsg(msg.c_str());

所以使用 std :: string + = (显然只有当我不需要自定义/数字格式化的工作速度比流版本快40%,而且据我所知,到 str()的完整多余副本。

解决方案

对于第二个项目符号


鉴于这似乎很容易,但实现这一点并不简单,有
任何变量 http://www.boost.org/doc/libs/1_55_0/libs/iostreams/doc/index.htmlrel =nofollow> Boost.Iostreams ,它甚至包含如何实现(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)
{}

//注意:这是flush的非const。
//次优,但是对于这个测试OK。
const wchar_t * c_str(){
flush();
return result.c_str();
}
};

在测试中,使用 c_str()帮助运行稍微快于正常 ostringstream 的速度,并且复制 str()。c_str()



我不包括测量代码。在这个领域的性能非常脆弱,确保自己测量你的用例! (例如,字符串流的构造函数开销是不可忽略的。)


Is there a canonical / public / free implementations variant of std::stringstream where I don't pay for a full string copy each time I call str()? (Possibly through providing a direct c_str() member in the osteam class?)

I've found two questions here:

And "of course" the deprecated std::strstream class does allow for direct buffer access, although it's interface is really quirky (apart from it being deprecated).

It also seems one can find several code samples that do explain how one can customize std::streambuf to allow direct access to the buffer -- I haven't tried it in practice, but it seems quite easily implemented.

My question here is really two fold:

  • Is there any deeper reason why std::[o]stringstream (or, rather, basic_stringbuf) does not allow direct buffer access, but only access through an (expensive) copy of the whole buffer?
  • Given that it seems easy, but not trivial to implement this, is there any varaint available via boost or other sources, that package this functionality?

Note: The performance hit of the copy that str() makes is very measurable(*), so it seems weird to have to pay for this when the use cases I have seen so far really never need a copy returned from the stringstream. (And if I'd need a copy I could always make it at the "client side".)


(*): With our platform (VS 2005), the results I measure in the release version are:

// 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());

So using a std::string with += (which obviously only works when I don't need custom/number formatting is 40% faster that the stream version, and as far as I can tell this is only due to the complete superfluous copy that str() makes.

解决方案

As for the second bullet

Given that it seems easy, but not trivial to implement this, is there any variant available via boost or other sources, that package this functionality?

There is Boost.Iostreams and it even contains an example of how to implement an (o)stream Sink with a string.

I came up with a little test implementation to measure it:

#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();
    }
};

In the tests I did, using this with it's c_str()helper ran slightly faster than a normal ostringstream with it's copying str().c_str() version.

I do not include measuring code. Performance in this area is very brittle, make sure to measure your use case yourself! (For example, the constructor overhead of a string stream is non-negligible.)

这篇关于std :: stringstream与直接输出缓冲区/字符串结果访问,避免复制?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆