依据前文,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 >= 201103L      // 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 <iostream>#include <fstream>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.左移位<<操作符

局部<<操作符函数原型如下:

    //重载一系列<<操作符,能够用于读取变量数据并放入到流缓冲区中      __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));      }

\<<操作符可用于将数据写入到输入流中,应用例子如下:

#include <iostream>#include <fstream>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 = 1234567;    out << i << endl << ll << endl;    return 0;}

这时咱们猜想,命令行规范输入中应该会输入两行数字,编译后执行后果如下:

12341234567

从这里out变量用法来看,实际上就是实现了规范库中cout的性能,当然,我是猜想可能是这样实现的。

/proc/self/fd/1是linux零碎中规范输入文件,所以关上这个文件操作的话,反映在程序执行的过程中,就是间接输入到规范输入。
3.put函数

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

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

put函数应用例子如下:

#include <iostream>#include <fstream>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 <iostream>#include <fstream>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 <iostream>#include <fstream>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内容,会看到0123456789曾经被写入到文件中去。

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

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

tellp函数原型如下:

//返回以后写缓冲区地位     pos_type      tellp();

应用例子如下:

#include <iostream>#include <fstream>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 <iostream>#include <fstream>using namespace std;int main(){    ofstream out("aaa.txt");    if ( !out.good())    {        cerr << "stream buf state is bad" << endl;        return -1;    }    out << 1234567;    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 7second pos is 3third pos is 1[root@mylinux ~]#

到这里,ostream类的public成员函数就介绍结束啦,若有不对之处,欢送斧正。