16

我的问题如下:Martin Yorkthisthisthis中声称可以stringstream通过使用如下方式从某个内存中进行读取basic_stringbuf::pubsetbuf

char buffer[] = "123";
istringstream in;
in.rdbuf()->pubsetbuf(buffer, sizeof(buffer)); // calls basic_stringbuf::setbuf
int num;
in >> num; // reads 123

不幸的是,我挖掘了整个标准,看不到它可以保证在哪里工作。我看到的是这只是实现定义的。事实上,在 Microsoft 的实现(也许对其他人也是)这个调用没有任何效果。

以下是我在上一个 C++0x 草案中找到的相关引用。对于basic_streambuf::setbuf[streambuf.virt.buffer]:

1效果:影响流缓冲的方式为本条款(27.8.1.4、27.9.1.5)中从 basic_streambuf 派生的每个类单独定义。

2默认行为: 什么都不做。返回这个。

然而,在派生类中,它似乎保留了行为实现定义。因为basic_stringbuf::setbuf它说[stringbuf.virtuals]:

1效果: 实现定义,除了 setbuf(0,0) 没有效果。

因为basic_filebuf::setbuf它说[filebuf.virtuals]:

12效果:如果 setbuf(0,0) [...],则流变为无缓冲。否则结果是实现定义的。“无缓冲” [...]

就是这样。所以正如我所看到的,一个有效的实现可以完全忽略这些调用(对于非空参数)。

我错了吗?标准的正确解释是什么?C++98/03/0x 有同样的保证吗?您是否有更多关于上述代码在哪些实现上起作用以及在哪些实现上不起作用的统计数据?basic_streambuf::setbuf打算如何使用?

4

2 回答 2

8

我相信它是实现定义的,并且您提供了相关的报价。

作为记录,这就是Standard C++ IOStreams and locales,我不得不承认的不是最近的一本书,在标题为“几乎没有语义的函数-setbuf() ”的部分中必须对这个主题说:

虚拟成员函数setbuf() 是一个相当特殊的流缓冲区成员。它的语义基本上是未定义的。对于字符串流缓冲区, 的语义setbuf()是实现定义的,但 setbuf(0, 0)定义如下:如果 setbuf(0, 0)之前在流上调用并且在该流上发生了 I/O,则流变为无缓冲,这意味着字符直接往返于文件系统。否则,结果是实现定义的。

但是, setbuf()forbasic_filebuf的 规范几乎没有对其他流缓冲区类型basic_stringbuf的语义提出任何要求 。setbuf()充其量,一般语义可以定义为设备,并且在用户定义的流缓冲区类型的情况下,可以定义为特定于实现的。

没有任何要求,您可以自由地setbuf()为几乎任何目的重新定义,并以适合 setbuf().

于 2010-12-06T21:50:22.633 回答
4

好的。收回。

在花了最后几天浏览文档和提出的建议之后,现在似乎很清楚这可能行不通(因为它是实现定义的)。

正如您在上面的描述中指出的那样:

27.5.2.4.2: 1 效果:影响流缓冲的方式为本条款(27.8.1.4、27.9.1.5)中从 basic_streambuf 派生的每个类单独定义。

setbuf() 的效果实际上是由它与 27.8.1.4 underflow() 的交互来定义的;

返回:如果输入序列有可用的读取位置,则返回 traits::to_int_type(*gptr())。否则,返回traits::eof()。底层缓冲区中已初始化的任何字符都被视为输入序列的一部分

此外,为了从流中获取更多字符,您需要检查 27.9.1.5 showmanyc()

如果一个实现可以确定可以从输入序列中读取更多字符,那么它很可能会为此函数签名提供一个覆盖定义。

对于 stringstream 缓冲区,这意味着它不会得到任何东西,因为缓冲区已经保存了整个流。

因此,尽管它是实现定义了它是如何做到的。
它仍然很好地定义了它是如何做到的。

于 2010-12-03T21:26:23.330 回答