C++ istream eof libc和x2B之间的差异+;和libstdc++;

C++ istream eof libc和x2B之间的差异+;和libstdc++;,c++,istream,libstdc++,libc++,C++,Istream,Libstdc++,Libc++,当链接到libstdc++和libc++时,下面的(toy)程序返回不同的内容。这是libc++中的一个bug还是我不明白istream eof()是如何工作的?我曾尝试在linux和mac os x上使用g++运行它,在mac os x上使用clang运行它,有无-std=c++0x。我的印象是,在尝试读取(通过get()或其他方法)实际失败之前,eof()不会返回true。这是libstdc++的行为方式,但不是libc++的行为方式 #include <iostream> #i

当链接到libstdc++和libc++时,下面的(toy)程序返回不同的内容。这是libc++中的一个bug还是我不明白istream eof()是如何工作的?我曾尝试在linux和mac os x上使用g++运行它,在mac os x上使用clang运行它,有无-std=c++0x。我的印象是,在尝试读取(通过get()或其他方法)实际失败之前,eof()不会返回true。这是libstdc++的行为方式,但不是libc++的行为方式

#include <iostream>
#include <sstream>

int main() {
    std::stringstream s;

    s << "a";

    std::cout << "EOF? " << (s.eof() ? "T" : "F") << std::endl;
    std::cout << "get: " << s.get() << std::endl;
    std::cout << "EOF? " << (s.eof() ? "T" : "F") << std::endl;

return 0;
}

Thor:~$ g++ test.cpp
Thor:~$ ./a.out
EOF? F
get: 97
EOF? F
Thor:~$ clang++ -std=c++0x -stdlib=libstdc++ test.cpp 
Thor:~$ ./a.out
EOF? F
get: 97
EOF? F
Thor:~$ clang++ -std=c++0x -stdlib=libc++ test.cpp 
Thor:~$ ./a.out
EOF? F
get: 97
EOF? T
Thor:~$ clang++ -stdlib=libc++ test.cpp 
Thor:~$ ./a.out
EOF? F
get: 97
EOF? T
#包括
#包括
int main(){
std::strings;

seofbit设置当有一个操作试图读取超过文件末尾时,该操作可能不会失败(如果您正在读取一个整数,并且该整数后面没有行尾,我希望设置eofbit,但读取该整数会成功)。即,我获得并期望FT

#include <iostream>
#include <sstream>

int main() {
    std::stringstream s("12");
    int i;
    s >> i;

    std::cout << (s.fail() ? "T" : "F") << (s.eof() ? "T" : "F") << std::endl;

    return 0;
}
#包括
#包括
int main(){
标准::串流(“12”);
int i;
s>>i;
std::cout第二次调用中未指定
s.eof()的值
对或错,甚至可能不一致。你能说的就是
如果
s.eof()
返回false,不能保证将来的输入会成功)。
失败(
s.fail()
)后,如果
s.eof()
返回true,则很可能(但是 不是100%确定)失败是由于文件结束。这是值得的 但是,考虑到以下情况:

double test;
std::istringstream s1("");
s1 >> test;
std::cout << (s1.fail() ? "T" : "F") << (s1.eof() ? "T" : "F") << endl;
std::istringstream s2("1.e-");
s2 >> test;
std::cout << (s2.fail() ? "T" : "F") << (s2.eof() ? "T" : "F") << endl;
双重测试;
std::istringstream s1(“”);
s1>>试验;

STD::CUT< P> <强>编辑< /St>:这是由于旧版本的LBC+++解释C++标准的缘故,解释在其中,被认为是不正确的,并且LBC+++被改变了。 当前的libc++在测试中给出的结果与libstdc++相同

旧答案:

你的理解是正确的

istream::get()
执行以下操作:

  • 调用
    good()
  • 必要时冲洗领带()
  • 如果此时
    good()
    为false,则返回eof,不执行其他操作
  • 通过调用
    rdbuf()->sbumpc()
    rdbuf()->sgetc()
    §27.7.2.1[istream]/2
    )提取字符
  • 如果
    sbumpc()
    sgetc()
    返回eof,则设置
    eofbit
    §27.7.2.1[istream]/3
    )和
    故障位
    §27.7.2.2.3[istream.未格式化]/4
  • 如果引发异常,则设置badbit(
    §27.7.2.2.3[istream.unformatted]/1
    )并在允许的情况下重新刷新
  • 更新gcount并返回字符(如果无法获取,则返回eof)
  • (引用自C++11的章节,但C++03在§27.6下具有所有相同的规则。*)

    现在让我们看一下实现:

    libc++(当前svn版本)将get()的相关部分定义为

    libstdc++(与gcc 4.6.2一起提供)定义了与

    sentry __cerb(*this, true);
    if (__cerb)
      {
        __try
          {
            __c = this->rdbuf()->sbumpc();
            // 27.6.1.1 paragraph 3
            if (!traits_type::eq_int_type(__c, __eof))
              _M_gcount = 1;
            else
              __err |= ios_base::eofbit;
          }
    [...]
    if (!_M_gcount)
      __err |= ios_base::failbit;
    
    如您所见,这两个库都调用
    sbumpc()
    ,并在且仅当sbumpc()返回eof时设置eofbit


    您的测试用例使用这两个库的最新版本为我生成相同的输出。

    这是一个libc++错误,正如Cubbi指出的那样已修复。我的错误。详细信息如下:


    如何未指定?标准很明确:如果sbumpc()/sgetc(),则设置failbit和eofbit返回eof,如果抛出异常则设置badbit。@Cubbi No.set
    eofbit
    if
    sgetc
    返回eof,但不一定是
    failbit
    ;前瞻总是合法的,有时是必要的。并且没有指定
    get
    调用
    sgetc
    的确切时间和频率。我将响应作为答案发布。这是wierd.我在我的标准版本(C++03和N3291)中找不到你引用的任何文本:我的两个版本都说,
    get
    “表现为一个未格式化的输入函数。在构造一个sentry对象后,提取一个字符C(如果有)。与调用
    rdbuf()->sbump()的次数无关
    rdbuf()->sgetc()
    。虽然我通常不希望这样,但对
    rdbuf()->sgetc()
    进行额外调用并因此设置
    eofbit
    的实现并没有违法之处。操作列表中有几点:关于第2点:
    istream::get()
    不这样做---这是
    sentry
    对象构造函数操作的一部分。关于第3点和第4点:标准约束要小得多。提取必须像调用
    rdbuf()->sbumpc()
    rdbuf()->sgetc()
    一样(这是一个错误,因为
    rdbuf()->sgetc())< /代码>不提取,和<代码> RDBUFF()> SNECTCE()/<代码>和>代码> RDBUF> > SGETNE()/>代码>,这不表示什么时候和如果向前看发生。@ JAMESKANZE关于哨兵,其构造函数的动作是<>代码> istRAM::GET()/C++ >的一部分。(有时也会)直接在
    get()中做一些它应该做的事情
    。关于对sgetc的额外调用——调用它或任何其他函数都没有违法之处,但是设置eofbit是违法的,因为它返回的内容违反了as if子句。调用
    streambuf
    中的任何函数都是可观察的行为(因为它们转发给用户定义的虚拟函数,这些虚拟函数通常可以进行系统调用)。而且所有的实现在看到文件结尾时都会设置
    eofbit
    。如果
    get()
    在这种特殊情况下通常不设置它,那是因为可以实现
    get()
    没有任何前瞻性。可以,不必。但标准
    sentry __cerb(*this, true);
    if (__cerb)
      {
        __try
          {
            __c = this->rdbuf()->sbumpc();
            // 27.6.1.1 paragraph 3
            if (!traits_type::eq_int_type(__c, __eof))
              _M_gcount = 1;
            else
              __err |= ios_base::eofbit;
          }
    [...]
    if (!_M_gcount)
      __err |= ios_base::failbit;