【问题标题】:inheriting ostream and streambuf problem with xsputn and overflow使用 xsputn 和溢出继承 ostream 和 streambuf 问题
【发布时间】:2011-08-04 06:22:09
【问题描述】:

我一直在研究如何创建我自己的 ostream 以及一个 streambuf 来处理我的 ostream 的缓冲区。我实际上大部分都在工作,我可以将 (

我浏览了代码,我看到流正在调用 do_put,然后是 f_put,它最终尝试将浮点数 1 字符一次放入缓冲区。如果我的缓冲区没有空间,我可以让它调用我的虚函数溢出(int c)的实现,从而获取浮点数和整数的数据。

现在问题来了,我需要知道何时将浮点数放入缓冲区。或者换一种说法,我需要知道这是最后一次为流入的特定值调用溢出的时间。xsputn 对我有用的原因是因为我预先获得了整个值及其长度。所以我可以将它复制到缓冲区中,然后调用等待缓冲区已满的函数。

我承认我滥用了 ostream 设计,因为我需要缓存输出,然后为每个输入值一次发送所有输出 (

无论如何,我会以另一种方式重申我的目标。我很有可能只是走错路了。

我想使用继承的 ostream 和 streambuf,以便我可以向其中输入值并允许它为我处理我的类型转换,然后我想将该信息传送到另一个对象,我将句柄传递给streambuf 到(对于?)。该对象具有昂贵的 i/o,因此我不想一次发送 1 个字符的数据。

如果不清楚,请提前抱歉。感谢您抽出宝贵时间。

【问题讨论】:

  • 这种设计的部分问题是假设您可以识别正在流式传输的各个值。当你有std::complex<T>::operator<<(ostream& os) 时,它必须调用os << real << imag。现在 值是什么?从逻辑上讲,复数是单个值,但<iostream> 将其视为 2。

标签: c++ iostream ostream streambuf


【解决方案1】:

不太清楚你在做什么,虽然听起来很粗略 正确的。可以肯定的是:您的所有ostream 所做的只是提供 方便的构造函数来创建和安装你的streambuf, 析构函数,可能是rdbuf 的实现 处理正确类型的缓冲区。假设这是真的: 在 streambuf 中定义 xsputn 纯粹是一种优化。 您必须定义的关键函数是overflow。最简单的 overflow 的实现只需要一个字符,并且 将其输出到接收器。除此之外的一切都是优化: 例如,您可以使用setp 设置缓冲区;如果你这样做 这个,然后overflow 只会在缓冲区被调用时 已满,或已请求刷新。在这种情况下,您必须 输出缓冲区(使用pbasepptr 来获取 地址)。 (streambuf 基类初始化 创建 0 长度缓冲区的指针,因此 overflow 将是 为每个字符调用。)您可能会使用的其他功能 想要在(非常)特定的情况下覆盖:

imbue: 如果你出于某种原因需要语言环境。 (请记住 当前字符编码是语言环境的一部分。)

setbuf:允许客户端代码指定一个缓冲区。 (恕我直言,这是 通常不值得费心,但你可能有特别的 要求。)

seekoff:支持求。我从来没有用过这个 我的streambufs,所以我不能提供任何信息 你可以阅读标准。

sync: 在刷新时调用,应该输出任何字符 缓冲到水槽。如果你从不打电话给setp(所以没有 缓冲区),你总是同步的,这可能是一个空操作。 overflowuflow 可以调用这个,或者两者都可以调用一些 单独的功能。 (关于sync的唯一区别 而uflowuflow 只有在存在的情况下才会被调用 缓冲区,如果缓冲区为空,则永远不会调用它。 如果客户端代码刷新流,将调用sync。)

在编写我自己的流时,除非性能要求 否则,我会保持简单,只覆盖overflow。 如果性能决定了缓冲区,我通常会将代码放在 将缓冲区刷新到单独的write(address, length) 函数,并沿线实现overflowsync 的:

int MyStreambuf::overflow( int ch )
{
    if ( pbase() == NULL ) {
        // save one char for next overflow:
        setp( buffer, buffer + bufferSize - 1 );
        if ( ch != EOF ) {
            ch = sputc( ch );
        } else {
            ch = 0;
        }
    } else {
        char* end = pptr();
        if ( ch != EOF ) {
            *end ++ = ch;
        }
        if ( write( pbase(), end - pbase() ) == failed ) {
            ch = EOF;
        } else if ( ch == EOF ) {
            ch = 0;
        }
        setp( buffer, buffer + bufferSize - 1 );
    }
    return ch;
}

int sync()
{
    return (pptr() == pbase()
            || write( pbase(), pptr() - pbase() ) != failed)
        ? 0
        : -1;
}

一般来说,我不会打扰xsputn,但如果您的客户 代码输出了很多长字符串,它可能很有用。 像这样的东西应该可以解决问题:

streamsize xsputn(char const* p, streamsize n)
{
    streamsize results = 0;
    if ( pptr() == pbase()
            || write( pbase(), pptr() - pbase() ) != failed ) {
        if ( write(p, n) != failed ) {
            results = n;
        }
    }
    setp( buffer, buffer + bufferSize - 1 );
    return results;
}

【讨论】:

  • 这基本上就是我现在正在做的事情,我想知道是否有办法告诉溢出将被调用多少次,或者最后一个字符何时过去。例如,如果我做 mystream
  • 代码无法提前知道客户端代码要做什么,或者要调用多少次。您可以在ostream 上设置unitbuf:这将导致sync 在每个operator<< 的末尾被调用(在sentry 对象的析构函数中)。然后,您对sync 中的缓冲区进行操作。
  • 啊哈!这正是我所需要的!将此标记为答案,但还不能投票,一旦我获得足够的代表,我会回来这样做。非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多