是否可以覆盖std :: istream读取方法?

时间:2017-06-01 14:31:11

标签: c++

我想使用std :: istream从给定的类中读取数据,该类只提供2种方法:

// Returns a byte from the stream (consuming it)
uint8_t getChar(OwnIOStream stream);
// Makes the passed pointer point to the data in the stream
bool getCharBlockPtr(OwnIOStream stream, uint8_t** buffer, uin32_t maxSize, uint32_t* size);

我首先想到继承stream_buf并使用getChar()方法实现下溢方法。但是我想使用getCharBlockPtr()来避免数据副本(我假设为每个读取字节调用下溢会降低性能)。问题是我需要事先知道每次我想要读取的字节数。这就是为什么我在考虑是否可以覆盖istream的read方法。

使用提升不是一种选择。

2 个答案:

答案 0 :(得分:0)

一般规则是标准C ++库中的大多数类都不是要派生的。这里的例外是streambuf类,它是IO支持的对象和C ++ stream之间的低级接口。

所以这里的标准方式是构建一个允许缓冲的自定义streambuf调用getChar或更好getCharBlockPtr。杰瑞的回答解释了如何做到这一点。

但看起来你有特殊要求:

  • 您在更高级别知道要阅读的字节数
  • 您正处于性能关键操作,并希望尽可能避免使用缓冲区副本 - 但最后一点应该在分析后进行审核...

然后,要求C ++流的全部功能可能不是可行的方法。构建一个只需要实现你需要调用的istream方法的自定义类,以及一些提取器,仍然可以在高级别提供一个很好的代码,并且可以在低级别提供更优化的代码。

但你和你才能知道:

  • 您的更高级代码是否需要C ++流 - 然后自定义类不是一个选项,您将不得不使用自定义streambuf
  • 是否可以直接从调用代码中将streambuf的预期大小作为提示。或多或少:

    class OwnStreamBuf: public std::streambuf {
        ...
        void sizehint(size_t hint) { /* size for next read access */
           this->hint = hint
        }
        int_type underflow() {
            ...
            cr = getCharBlockPtr(stream, buffer, hint, size); /* use hint as maxSize */
            ...
        }
    }
    ...
    OwnStreamBuf buf(...);
    class OwnIStream: public istream ...
    OwnIStream is(buf)
    ...
    buf.sizehint(n)
    is >> special_obj;
    ...
    
  • 您是否只需要少量提取器和自定义类,从头开始构建起来会更简单。

答案 1 :(得分:0)

从streambuf派生是一个非常有效的选择。

是否需要做多(如果有的话),而不是覆盖underflow。如果OwnIOStream已经在缓冲数据,那么就可以从中获得足够的性能。我会从那开始,看看情况如何。

下一个明显的步骤是使用getCharBlockPtrstreambuf有一个setg,用于设置指向缓冲区的开头,当前位置和结尾的指针。至少如果我正确地解释了事情,你会打电话给getCharBlockPtr并开始和结束。然后,您可以调用setg将开始和当前位置设置为开头,将结束位置设置为结束。从那里,streambuf 能够直接从缓冲区读取数据。当它用完时,它会调用underflow,您需要再次获取更多数据。

一个注意事项:它看起来不像OwnIOStream支持回退区域,这些流通常会支持。让它正常工作(特别是在缓冲区的开头放回一个字符)可能在某种程度上无法正常支持。