C++ 使用xsputn和溢出继承ostream和streambuf问题
我一直在研究如何创建自己的ostream,以及如何使用streambuf来处理ostream的缓冲区。实际上,我的大部分工作正常,我可以插入(你在做什么不太清楚,尽管听起来很粗略 好的。请确定:您的C++ 使用xsputn和溢出继承ostream和streambuf问题,c++,iostream,ostream,streambuf,C++,Iostream,Ostream,Streambuf,我一直在研究如何创建自己的ostream,以及如何使用streambuf来处理ostream的缓冲区。实际上,我的大部分工作正常,我可以插入(你在做什么不太清楚,尽管听起来很粗略 好的。请确定:您的ostream所做的就是提供 方便的构造函数创建和安装您的streambuf, 一个析构函数,可能是rdbuf的一个实现 处理正确类型的缓冲区。假设这是真的: 在streambuf中定义xsputn纯粹是一种优化。 您必须定义的关键函数是溢出 溢出的实现只需要一个字符,并且 将其输出到接收器。除此之外
ostream
所做的就是提供
方便的构造函数创建和安装您的streambuf
,
一个析构函数,可能是rdbuf
的一个实现
处理正确类型的缓冲区。假设这是真的:
在streambuf
中定义xsputn
纯粹是一种优化。
您必须定义的关键函数是溢出
溢出
的实现只需要一个字符,并且
将其输出到接收器。除此之外的一切都是优化:
例如,如果需要,可以使用setp
;设置缓冲区
只有在缓冲区被调用时,才会调用此溢出
已满或已请求同花顺。在这种情况下,您必须
输出缓冲区(使用pbase
和pptr
获取
(streambuf基类初始化
用于创建0长度缓冲区的指针,因此溢出将
为每个字符调用。)您可能需要的其他函数
要在(非常)特定的情况下覆盖:
imbue
:如果您出于某种原因需要区域设置(记住这一点)
当前字符编码是区域设置的一部分。)
setbuf
:允许客户机代码指定缓冲区
通常不值得麻烦,但你可能有特殊的
要求。)
seekoff
:支持查找。我从未在任何一个应用程序中使用过此功能
我的streambuf
s,因此我无法提供任何信息
你可以在标准中阅读
sync
:在flush时调用,应在
缓冲区到接收器。如果您从未调用setp
(因此没有
缓冲区),您始终处于同步状态,这可能是不可操作的。
overflow
或uflow
可以调用这个,或者两者都可以调用一些
独立功能。(关于sync
而uflow
是指只有在存在时才会调用uflow
缓冲区,如果缓冲区为空,则永远不会调用它。
如果客户端代码刷新流,将调用sync
。)
在编写自己的流时,除非性能要求
否则,我将保持它的简单性,只覆盖溢出
。
如果性能决定了缓冲区,我通常会将代码放入
将缓冲区刷新为单独的写入(地址、长度)
功能,并沿线路执行溢出
和同步
其中:
一般来说,我不会为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
上的etunitbuf
:这将导致在每个操作结束时调用sync
。这正是我所需要的!将此标记为答案,现在还不能投票,但一旦获得足够的代表,我会回来这样做。非常感谢。此设计的部分问题在于假设当您有std::complex::operator时
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;
}