C++ 是否可以重写std::istream读取方法?

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

我想使用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()方法实现underflow方法。但是,我希望使用getCharBlockPtr()来避免数据的拷贝(我假设为每个读取字节调用underflow会降低性能)。问题是我需要提前知道每次要读取的字节数。这就是为什么我在想是否有可能覆盖istream的read方法


使用Boost不是一个选项。

一般规则是,大多数来自标准C++库的类不是要导出的。这里的例外是 StRuBF类,它是IO对象和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将请求多少字节,我不想制作额外的副本。