为什么stringstream >>在失败时改变目标值?

use*_*664 53 c++ state stringstream cin

来自Stroustrup的TC++ PL,第3版,第21.3.3节:

如果我们尝试读入变量v并且操作失败,则v的值应该保持不变(如果v是istream或ostream成员函数处理的类型之一,则它不会改变).

以下示例似乎与上述引用相矛盾.基于上面的引用,我期待v的值保持不变 - 但它会变为零.对这种明显的矛盾行为有什么解释?

#include <iostream>
#include <sstream>

int main( )
{
    std::stringstream  ss;

    ss  << "The quick brown fox.";

    int  v = 123;

    std::cout << "Before: " << v << "\n";

    if( ss >> v )
    {
        std::cout << "Strange -- was successful at reading a word into an int!\n";
    }

    std::cout << "After: " << v << "\n";

    if( ss.rdstate() & std::stringstream::eofbit  ) std::cout << "state: eofbit\n";
    if( ss.rdstate() & std::stringstream::failbit ) std::cout << "state: failbit\n";
    if( ss.rdstate() & std::stringstream::badbit  ) std::cout << "state: badbit\n";

    return 1;
}
Run Code Online (Sandbox Code Playgroud)

我使用x86_64-w64-mingw32-g ++.exe(rubenvb-4.7.2-release)4.7.2获得的输出是:

Before: 123
After: 0
state: failbit
Run Code Online (Sandbox Code Playgroud)

谢谢.

Som*_*ude 59

这个参考:

如果提取失败(例如,如果输入了预期数字的字母),则值保持不变,并设置failbit(直到C++ 11)

如果提取失败,则将零写入值并设置failbit.如果提取导致值太大或太小而不适合值,则写入std :: numeric_limits :: max()或std :: numeric_limits :: min()并设置failbit标志.(自C++ 11以来)

您的编译器似乎正在以C++ 11模式进行编译,这会改变行为.


输入运算符使用std::num_getget函数调用的语言环境facet do_get.对于C++ 11,它指定使用std::strtollet.人.功能类型.在C++ 11之前,它显然使用std::scanf样式解析(通过引用,我无法访问C++ 03规范)来提取数字.行为的改变是由于解析输入的这种变化.

  • 有趣的变化,我从来不知道.我总是将提取失败后读取变量视为未定义的行为... (7认同)
  • @KerrekSB:我也是. (2认同)
  • 这个答案并不能说明问题的全部内容:如果构造哨兵对象失败,那么我们就没有“如果提取失败,则将零写入值”。如果流已经设置了错误条件或仅包含空格,则会发生这种情况。(哨兵执行空白跳)。在这种情况下将保留原始值 (2认同)