难道 istream::peek() 不应该总是返回你刚刚放回的内容吗?(涉及 IT 技术并且是一个提问标题)

11

从C++规范来看,直觉上我认为istream::putback(c)应该总是安排输入缓冲区,以便下一次调用istream::peek()读取字符c。这不正确吗?我问这个问题是因为随附于Xcode 4.6的最新版本的libc++在某些情况下似乎没有强制执行这种行为——特别是当最后一个字符在EOF时。如果您使用unget()而不是putback(c),则结果也是相同的。

libc++的行为是否正确,还是我的关于putback()/unget()应该如何工作的直觉是正确的?

请考虑以下示例代码,该代码适用于libstdc++但不适用于libc++(断言失败)。

#include <sstream>
#include <cassert>

int main(int argc, const char * argv[])
{
    std::istringstream in( "[Test]" );

    while( in )
    {
        int c = in.get();
        if( c == ']' )
        {
            in.putback( c );
            assert( in.peek() == c );   // Fails with libc++. Succeeds with libstdc++.
            break;
        }
    }

    return 0;
}

2
putback(c)之后,eofbitfailbitbadbit中是否有任何一个被设置?(参考:使用libstdc++ 4.7时,这些标志都没有被设置,流是good()的。) - us2012
两个答案都加一。看起来是libc++中的一个错误,在r162608中已经修复了。 - Howard Hinnant
2个回答

6
在C++11中,putback函数发生了变化:
§27.7.2.3/34

basic_istream<charT,traits>& putback(char_type c);

效果:表现为一个未格式化的输入函数(如27.7.2.3第1段所述),但该函数首先清除eofbit。...

在C++03中,这个句子的后半部分不存在。
因此,这可能取决于编译器是否完全实现了这个更改,或者您是否使用了所需的选项(-std=C++11?)。

4

Bo Persson关于标准的说法是正确的。您可能正在使用较旧版本的libc++(您的问题在LLVM bugtracker中,请参见下文)。

此更改已在162108修订版中引入:

--- istream     (revision 162607)
+++ istream     (revision 162608)
@@ -1263,6 +1263,7 @@
     try
     {
 #endif  // _LIBCPP_NO_EXCEPTIONS
+        this->clear(this->rdstate() & ~ios_base::eofbit);
         sentry __sen(*this, true);
         if (__sen)
         {

有关更改的日志:

$ svn log -r 162608

------------------------------------------------------------------------ r162608 | hhinnant | 2012-08-25 00:03:03 +0200 (周六,2012年8月25日) | 1 行

首先清除 eofbit,修复了 basic_istream seekg、putback 和 unget 的问题。修复了 http://llvm.org/bugs/show_bug.cgi?id=13089


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接