basic_ios上的标志语义

我发现自己反复被rdstate()标志困惑 – good()bad()eof()fail() – 以及它们在basic_ios::operator!中的expression方式basic_ios::operator!operator booloperator void*

有人能把我从痛苦中解脱出来吗,所以我再也不用再考虑了。

有三个标志表示错误状态:

  • badbit意味着stream中出现了一些错误。 无论是向数据stream中提供数据,可能是缓冲区错误或错误。 如果这个标志被设置,那么很可能你将不再使用这个stream。

  • 失败failbit表示从stream中提取或读取失败(或输出stream的写入或插入),并且您需要知道该失败。

  • eofbit意味着inputstream已经到了最后,没有什么可读的。 请注意,只有在您尝试读取已达到其结尾的inputstream(即由于您尝试读取不存在的数据而发生错误时设置)时,才会设置此项。

failbit也可以通过许多到达EOF的操作来设置。 例如,如果stream中只剩下空白,并且您尝试读取一个int ,那么您都将达到EOF,并且将无法读取该int ,因此这两个标志都将被设置。

fail()函数testingbadbit || failbit badbit || failbit

good()函数testing!(badbit || failbit || eofbit) 。 也就是说,当没有设置任何位时,stream是好的。

你可以通过使用ios::clear()成员函数来重置标志。 这允许你设置任何错误标志; 默认情况下(不带参数),它清除所有三个标志。

stream不会重载operator bool() ; operator void*()用于实现安全布尔成语的有些破碎的版本。 如果设置了badbitfailbit则此运算符重载返回null,否则返回非null。 您可以使用这个来支持将提取成功作为循环或其他控制stream程语句的条件进行testing的习惯用法:

 if (std::cin >> x) { // extraction succeeded } else { // extraction failed } 

operator!()重载与operator void*()相反。 如果badbitfailbit被设置,则返回true否则返回falseoperator!()重载不再是真正需要的了; 它可以追溯到操作符重载完全一致的支持(请参阅sbi的问题“为什么std :: basic_ios重载一元逻辑否定运算符?” )。

C ++ 0x修复了导致我们不得不使用安全布尔成语的问题,因此在C ++ 0x中, basic_ios基类模板确实将operator bool()重载为显式转换运算符; 该运算符与当前operator void*()具有相同的语义。

除了詹姆斯的回答之外 ,记住这些标志表示操作的结果是很重要的,所以除非你执行一个操作,否则不会被设置。

一个常见的错误是这样做的:

 #include <fstream> #include <iostream> #include <string> int main() { std::ifstream file("main.cpp"); while (!file.eof()) // while the file isn't at eof... { std::string line; std::getline(file, line); // ...read a line... std::cout << "> " << line << std::endl; // and print it } } 

这里的问题是eof()将不会被设置,直到我们试图获得最后一行,在这一点上,stream将会说“不,不再有! 并设置它。 这意味着“正确”的方式是:

 #include <fstream> #include <iostream> #include <string> int main() { std::ifstream file("main.cpp"); for (;;) { std::string line; std::getline(file, line); // read a line... if (file.eof()) // ...and check if it we were at eof break; std::cout << "> " << line << std::endl; } } 

这将支票放在正确的位置。 虽然这是非常不羁的; 对我们来说幸运的是, std::getline的返回值是stream,stream有一个转换运算符,它允许在布尔上下文中进行testing,其值为fail() ,其中包括eof() 。 所以我们可以写:

 #include <fstream> #include <iostream> #include <string> int main() { std::ifstream file("main.cpp"); std::string line; while (std::getline(file, line)) // get line, test if it was eof std::cout << "> " << line << std::endl; }