依据前文,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;
}
这时咱们猜想,命令行规范输入中应该会输入两行数字,编译后执行后果如下:
1234
1234567
从这里 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 7
second pos is 3
third pos is 1
[root@mylinux ~]#
到这里,ostream 类的 public 成员函数就介绍结束啦,若有不对之处,欢送斧正。