文章目录

  • 1.流的状态
  • 2.流的定位
  • 3.流的同步


1.流的状态

iostream性能问题 iostream出错_输出流

  1. 流的状态:流的状态都是位掩码类型,如果iostate是char类型,那么可能的定义如下:
  2. 流的状态举例
// 1.badbit:不可恢复的错误
std::ofstream outFile;
outFile << 10;  // 没有关联文件,bagbit错误

// 2.failbit:输入输出操作失败(格式化或提取错误),可恢复
int x;
std::cin >> x;  // 如果终端输入hello,由于想要的是int,输入是字符串,所以失败

 // 3.eofbit:关联的输入序列已抵达文件尾
 int x;
 std::cin >> x;  // 终端输入ctrl+d,表示输入结束
  1. 检测流的状态:见下图。其中需要注意的有几点:
  • good状态只有在所有的标志位都没有置位的时候才是true
  • 只要bad状态是true,那么fail状态一定是true,这个也很好理解,因为bad状态的严重程度比fail更强,所以是bad一定是fail
  • 只要failbit/badbit没有置位,即使eofbit置位了,那么把流状态转化成bool值的结果也是true,因为经常写下面的代码,这个时候即使eofbit置位了,但是也是成功读取了,所以流的状态是正常的。
  1. 复位流的状态

2.流的定位

iostream性能问题 iostream出错_数据结构_02

  1. 获取流的位置:注意tellgg就是get,所以是获取输入流的位置;tellpp就是put,所以是获取输出流的位置。返回的结果是pos_type类型,但是这个类型到底是int还是long等没有明确的定义,但是他一定是一个整数。
  • tellg实例:
  • iostream性能问题 iostream出错_数据结构_03


  • tellp实例:
  • iostream性能问题 iostream出错_输出流_04


  1. 设置流的位置
  • 注意对于输出流来说,移动了流的位置之后,会对后面的内容进行覆盖,而不是插入。
  • 为什么输入流和输出流还要用gp来区分输入输出的位置?这是因为对于普通的fstream/stringstream来说,既可以输入也可以输出,那么他就包含输入位置、输出位置两个,所以要使用两个g/p来标识输入/输出的位置。
  • 设置流的位置有两种重载的方式,一种是绝对位置,一种是相对位置:
  • iostream性能问题 iostream出错_c++_05

    iostream性能问题 iostream出错_输出流_06


  • iostream性能问题 iostream出错_iostream性能问题_07


3.流的同步

iostream性能问题 iostream出错_输出流_08

  1. 对于输出流的flush同步,有两种方法:一个是std::flush,这个是一个操作符,和std::endl类似。另一个是std::baisc_iostream::flush,这个则是iostream的一个方法。所以二者使用方式是不同的,如下所示:
// 使用操作符刷新输出流
std::cout << "hello" << std::flush;  
// 使用类 的方法刷新输出流
std::cout << "hello";
std::cout.flush();
  1. 输入流sync()同步的使用较少,可以不用特别关注。

  2. 使用unitbuf操作符可以实现每次输出后自动同步,从字面上理解这个操作符就是把输出流的缓冲区大小设置成1,所以这样只要一往缓冲区写入内容就会输出。如下所示:
  3. iostream性能问题 iostream出错_c++_09

  4. 另外:关于coutcerr的一个区别就是,cout默认有缓冲区,因为他是标准输出,信息没有那么重要;而cerr默认没有缓冲区,也就是设置成了unitbuf,因为它是标准错误输出,信息非常重要,一旦有错误就要及时输出。
  5. 基于绑定的同步:这样的好处是在操作流的时候会刷新它绑定的输出流,从而保证输出流的内容可以被显示。比如如下的例子,cin绑定到了cout上,在调用cin之前,就可以保证cout的缓冲区一定可以被刷新,也就是内容一定可以显示。

std::cout << "What't you name?\n";
std::string name;
std::cin >> name;
  1. C++和C语言的IO同步
  2. iostream性能问题 iostream出错_数据结构_10