C++ 是否可以重写std::istream读取方法?
我想使用std::istream从只提供2种方法的给定类读取数据:C++ 是否可以重写std::istream读取方法?,c++,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 max
// 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()方法实现underflow方法。但是,我希望使用getCharBlockPtr()来避免数据的拷贝(我假设为每个读取字节调用underflow会降低性能)。问题是我需要提前知道每次要读取的字节数。这就是为什么我在想是否有可能覆盖istream的read方法
使用Boost不是一个选项。
一般规则是,大多数来自标准C++库的类不是要导出的。这里的例外是
调用streambuf
或更好的getChar
,允许缓冲。杰瑞的回答解释了怎么做getCharBlockPtr
- 在更高的级别上,您知道要读取的字节数
- 您正处于一个性能关键的操作中,如果可能的话,您希望避免缓冲区复制-但最后一点应该在分析之后进行检查
那么,要求C++流的全部能量可能不是可行的方法。构建一个只实现需要调用的
istream
方法的自定义类,以及少数提取器,仍然可以在高级别生成一个好的代码,并在低级别生成一个更优化的代码
但只有你知道:
- 您的高级代码是否需要C++流——那么自定义类不是一个选项,您必须使用自定义的StRIPBUF
- 是否可以直接从调用代码中为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; ...
- 无论您是否只需要少数提取器和自定义类,从头开始构建都会更简单
- 从streambuf派生是一个非常有效的选项
您是否需要做更多的工作(如果有的话)而不是覆盖
下溢
取决于您自己。如果OwnIOStream
已经在缓冲数据,那么您可以通过这样做获得足够的性能。我会先这样做,看看事情进展如何
下一个明显的步骤是使用getCharBlockPtr
。streambuf
有一个setg
,用于设置指向缓冲区开始、当前位置和结束的指针。至少如果我解释正确,您可以调用getCharBlockPtr
并获取开头和结尾。然后调用setg
将开始和当前位置设置为开始,将结束设置为结束。从那里,streambuf应该能够直接从缓冲区读取数据。当它用完时,它将调用underflow
,您需要再次获取更多数据
注意:它看起来不像
OwnIOStream
支持一个putback区域,而流通常希望支持这个区域。要使其正常工作(特别是在缓冲区开始时放回字符)可能需要正确支持。是否可以在streambuf
实现中使用内部缓冲区并在underflow()中填充getCharBlockPtr
?否,我想避免复制数据。我需要直接使用getCharBlockPtr提供的缓冲区(即直接将内容放入一个文件中,而不需要额外的副本)。在您的评论之后,我可以找到to子类streambuf。一旦你实现了一个内部缓冲区,放回区就可以使用它。是的,一旦你创建了一个缓冲区,它就可以被使用。这里的要点是使用现有的缓冲区,而不是创建另一个缓冲区。通常,当您创建缓冲区时,会在开始时为回拨区域留出一些空间——但是如果您使用的是没有为回拨区域留出空间的现有缓冲区,则可能会更加困难。OwnIOStream可能已经在缓冲数据,尽管我无法访问其内部代码。我在这里担心的是,如果我使用OwnIOStream提供的getChar方法实现每次调用一个字节时读取一个字节的下溢,那么性能可能会非常差。这就是为什么我想改用getCharBlockPtr。我发现的问题是,我不知道istream将请求多少字节,我不想制作额外的副本。