c++中ostream类的超详细说明

c++中ostream类的超详细说明p 根据前文 ostream 类是 c 标准输出流的一个基类 本篇详细介绍 ostream 类的主要成员函数用法 ph5id 1ostream 的构造函数 1 ostream 的构造函数 h

根据前文,ostream类是c++标准输出流的一个基类,本篇详细介绍ostream类的主要成员函数用法。

1.ostream的构造函数

从ostream头文件中截取一部分关于构造函数的声明和定义,如下:

public: //explicit用来防止由构造函数定义的隐式转换 explicit basic_ostream(__streambuf_type* __sb) { 
    this->init(__sb); } protected: basic_ostream() { 
    this->init(0); } #if __cplusplus >= L // Non-standard constructor that does not call init() basic_ostream(basic_iostream<_CharT, _Traits>&) { 
    } basic_ostream(const basic_ostream&) = delete; basic_ostream(basic_ostream&& __rhs) : __ios_type() { 
    __ios_type::move(__rhs); } // 27.7.3.3 Assign/swap basic_ostream& operator=(const basic_ostream&) = delete; basic_ostream& operator=(basic_ostream&& __rhs) { 
    swap(__rhs); return *this; } 

可以看到ostream类的默认构造函数是保护类型,而带参数的构造函数则是公有的,根据public和protected的功能,我们要定义一个ostream对象,必须要在参数中传入streambuf类型的指针才可以,否则会报编译错误。

一个可用的例子如下:

#include  
     #include  
     using namespace std; int main() { 
    filebuf buf; if ( buf.open("/proc/self/fd/1", ios::out) == nullptr ) { 
    cerr << "stdout open failed" << endl; return -1; } ostream out(&buf); return 0; } 

与istream一样,因为streambuf类型的构造函数是保护类型,不能直接使用,所以需要使用它的继承者stringbuf或者filebuf,这里使用了filebuf,并且我们输出错误信息没有使用cout,这里使用了ostream定义的另外一个实例cerr,会输出错误信息到标准错误输出。

ostream类与istream类一样,它的的拷贝构造函数和赋值函数也都是保护类型的,所以ostream是不允许拷贝或者赋值的,所以它也不能直接作为返回类型和参数传递,很多时候需要使用引用来进行传递。

2.左移位< <操作符< h5="">

部分< <操作符函数原型如下:< p="">

 //重载一系列< 
     <操作符,可以用于读取变量数据并放入到流缓冲区中< span="">
       __ostream_type 
      & 
      operator 
      << 
      ( 
      long __n 
      ) 
      { 
        
      return 
      _M_insert 
      (__n 
      ) 
      ; 
      } __ostream_type 
      & 
      operator 
      << 
      ( 
      unsigned 
      long __n 
      ) 
      { 
        
      return 
      _M_insert 
      (__n 
      ) 
      ; 
      } __ostream_type 
      & 
      operator 
      << 
      ( 
      bool __n 
      ) 
      { 
        
      return 
      _M_insert 
      (__n 
      ) 
      ; 
      } __ostream_type 
      & 
      operator 
      << 
      ( 
      short __n 
      ) 
      ; __ostream_type 
      & 
      operator 
      << 
      ( 
      unsigned 
      short __n 
      ) 
      { 
        
      // _GLIBCXX_RESOLVE_LIB_DEFECTS 
      // 117. basic_ostream uses nonexistent num_put member functions. 
      return 
      _M_insert 
      ( 
      static_cast 
      < 
      unsigned 
      long 
      > 
      (__n 
      ) 
      ) 
      ; 
      } __ostream_type 
      & 
      operator 
      << 
      ( 
      int __n 
      ) 
      ; __ostream_type 
      & 
      operator 
      << 
      ( 
      unsigned 
      int __n 
      ) 
      { 
        
      // _GLIBCXX_RESOLVE_LIB_DEFECTS 
      // 117. basic_ostream uses nonexistent num_put member functions. 
      return 
      _M_insert 
      ( 
      static_cast 
      < 
      unsigned 
      long 
      > 
      (__n 
      ) 
      ) 
      ; 
      } 
     

< <操作符可用于将数据写入到输出流中,使用例子如下:< p="">

#include 
    
      #include 
     
       using namespace std; int main() { filebuf buf; if ( buf.open("/proc/self/fd/1", ios::out) == nullptr ) { cerr << "stdout open failed" << endl; return -1; } ostream out(&buf); int i = 1234; long long ll = ; out << i << endl << ll << endl; return 0; } 
      
    

这时我们猜测,命令行标准输出中应该会输出两行数字,编译后执行结果如下:

1234  

从这里out变量用法来看,实际上就是实现了标准库中cout的功能,当然,我是猜测可能是这样实现的。

/proc/self/fd/1是linux系统中标准输出文件,所以打开这个文件操作的话,反映在程序执行的过程中,就是直接输出到标准输出。

3.put函数

ostream头文件中put函数原型如下:

 //往缓冲区中插入一个字符 __ostream_type& put(char_type __c); 

put函数使用例子如下:

#include  
       #include  
       using namespace std; int main() { 
      filebuf buf; if ( buf.open("/proc/self/fd/1", ios::out) == nullptr ) { 
      cerr << "stdout open failed" << endl; return -1; } ostream out(&buf); char c = 'X'; out.put('c').put('=').put(c).put('\n'); return 0; } 

这里因为put函数返回的是ostream&类型,所以可以连着使用put函数,代码编译后执行结果如下:

[root@mylinux ~]# ./a.out c=X [root@mylinux ~]# 
4.write函数

ostream的write函数原型如下:

 //将__s指针所指向的字符串复制出来并插入到缓冲区中,最多插入__n个字符 __ostream_type& write(const char_type* __s, streamsize __n); 

用法如下:

#include  
       #include  
       using namespace std; int main() { 
      filebuf buf; if ( buf.open("/proc/self/fd/1", ios::out) == nullptr ) { 
      cerr << "stdout open failed" << endl; return -1; } ostream out(&buf); if ( !out.good()) { 
      cerr << "stream buf state is bad" << endl; return -1; } out.write("aaa\n", 4); return 0; } 

good函数是ostream继承于父类ios的一个成员函数,它用来检查流的状态是否正常,正常则返回true。

代码编译执行后结果如下:

[root@mylinux ~]# ./a.out aaa [root@mylinux ~]# 
5.flush函数

函数原型如下:

//将数据从缓冲区同步到存储介质中 __ostream_type& flush(); 

使用方法如下:

#include  
       #include  
       using namespace std; int main() { 
      ofstream out("aaa.txt"); if ( !out.good()) { 
      cerr << "stream buf state is bad" << endl; return -1; } for (int n=0; n<10; ++n) { 
      out << n; //out.flush(); } while(1); out.close(); return 0; } 

这里使用了ofstream类型,它是ostream的一个子类,所以对于flush用法是一样的,这里我们先把flush函数调用注释掉,此时去执行代码,然后查看aaa.txt文件,会发现数据并没有写入到文件中去,然后我们把注释取消,重新编译执行后,查看aaa.txt内容,会看到0已经被写入到文件中去。

按照我的理解,ofstream在往文件中写入数据时,数据实际上是先写到缓冲区中,并没有写到文件中去,所以需要调用一个flush,来确保数据会从缓冲区写到输出设备,也就是文件中去。

这里有一个小插曲,我一开始使用了out << n << endl去往文件写数据,发现flush是不起作用的,一直很疑惑,后来看源代码才发现endl这个操纵算子,它会调用先往缓冲区写入一个换行符然后再调用flush函数,所以flush才会不起作用。

6.tellp函数

tellp函数原型如下:

//返回当前写缓冲区位置 pos_type tellp(); 

使用例子如下:

#include  
       #include  
       using namespace std; int main() { 
      ofstream out("aaa.txt"); if ( !out.good()) { 
      cerr << "stream buf state is bad" << endl; return -1; } for (int n=0; n<10; ++n) { 
      out << n << endl; out.flush(); } clog << "current pos is " << out.tellp() <<endl; out.close(); return 0; } 

从代码分析,目前应该是写到了20的位置,编译执行,结果如下:

[root@mylinux~]# ./a.out current pos is 20 [root@mylinux~]# 
7.seekp函数

seekp函数原型如下:

 / 从当前位置开始,跳转pos个写位置 */ __ostream_type& seekp(pos_type pos); / 根据ios_base::seekdir定义的位置,跳转off个写位置 */ __ostream_type& seekp(off_type off, ios_base::seekdir); 

实例如下:

#include  
       #include  
       using namespace std; int main() { 
      ofstream out("aaa.txt"); if ( !out.good()) { 
      cerr << "stream buf state is bad" << endl; return -1; } out << ; clog << "first pos is " << out.tellp() <<endl; out.seekp(3); clog << "second pos is " << out.tellp() <<endl; out.seekp(1, ios::beg); clog << "third pos is " << out.tellp() <<endl; out.close(); return 0; } 

输出结果如下:

[root@mylinux ~]# ./a.out first pos is 7 second pos is 3 third pos is 1 [root@mylinux ~]# 

到这里,ostream类的public成员函数就介绍完毕啦,若有不对之处,欢迎指正。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/229285.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月16日 下午5:03
下一篇 2026年3月16日 下午5:03


相关推荐

  • JointJS总结

    JointJS总结JointJS 图库允许用户为所有当前的浏览器创建完全交互的绘图工具 JointJS 不仅是一个图库 其 MVC 更多的是 MV 架构将图 元件 element 和连接 link 模型与绘制分离

    2025年6月25日
    24
  • 一文让你知道为什么学了PHP的都要转学Go语言[通俗易懂]

    一文让你知道为什么学了PHP的都要转学Go语言

    2022年2月12日
    42
  • PostgreSQL 10.1 手册_部分 III. 服务器管理_第 20 章 客户端认证

    PostgreSQL 10.1 手册_部分 III. 服务器管理_第 20 章 客户端认证

    2021年6月14日
    86
  • C语言volatile关键字详解

    C语言volatile关键字详解1.volatile和什么有关百度翻译是这样子翻译volatile的:图1-1百度翻译volatile截图volatile属于C语言的关键字,《CPrimerPuls》是这样解释关键字的:关键字是C语言的词汇,由于编译器…

    2022年7月11日
    20
  • clion永久激活(注册激活)

    (clion永久激活)好多小伙伴总是说激活码老是失效,太麻烦,关注/收藏全栈君太难教程,2021永久激活的方法等着你。https://javaforall.net/100143.htmlIntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,上面是详细链接哦~2JTX0APX6F-eyJsaWNlbnNlSWQiOi…

    2022年3月29日
    528
  • MYSQL和SQL的区别

    MYSQL和SQL的区别什么是SQL?SQL是一种用于操作数据库的语言。SQL是用于所有数据库的基本语言。不同数据库之间存在较小的语法更改,但基本的SQL语法基本保持不变。SQL是StructuredQueryLanguage的简短缩写。根据ANSI(美国国家标准协会),SQL是操作关系数据库管理系统的标准语言。SQL用于访问,更新和操作数据库中的数据。它的设计允许管理RDBMS中的数据,例如MYSQL。SQL语言还用于控制数据访问以及数据库模式的创建和修改。什么是MYSQL?MySQL是在90年代中期开发的,是

    2022年10月2日
    4

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号