输入输出流,看似复杂却更好用----小话c++(2) (四)

2014-11-24 12:01:29 · 作者: · 浏览: 3
n 0;
}在中间两条cout语句和return 0; 处打上断点,调试运行:

运行到cout << "ok\n"时,上面的"hello"并没有被输出,这说明在缓冲区中;当运行到cout << endl;时,hellook\n均输出了,这说明\n确实导致了刷新缓冲区。当然也有可能是缓冲区太小(虽然不太可能是实际的状态),把cout << "ok\n";改为cout << "ok";后再次调试到此,hellook并没有输出。 运行到return 0; 时发现thanks没有被输出,运行完,thanks才输出。

当然,可以肯定的是,使用\n可能不会刷新缓冲区,但是endl一定会刷新缓冲区。

[cpp] template
inline basic_ostream<_CharT, _Traits>&
endl(basic_ostream<_CharT, _Traits>& __os)
{ return flush(__os.put(__os.widen('\n'))); }
template
inline basic_ostream<_CharT, _Traits>&
endl(basic_ostream<_CharT, _Traits>& __os)
{ return flush(__os.put(__os.widen('\n'))); }

Q: 经常使用cout的setf函数、flags函数以及使用操作子比如hex, dec等,这样可能造成一个后果:此时输出流的状态已经不是很确定了,怎么很好地区分它们的作用?

A: 看源码是了解一个问题最直接的方式。

如下setf函数源码:

[cpp] inline fmtflags
setf(fmtflags __fmtfl)
{
fmtflags __old = _M_flags;
_M_flags |= __fmtfl;
return __old;
}
inline fmtflags
setf(fmtflags __fmtfl)
{
fmtflags __old = _M_flags;
_M_flags |= __fmtfl;
return __old;
}如下flags源码:
[cpp] inline fmtflags
flags(fmtflags __fmtfl)
{
fmtflags __old = _M_flags;
_M_flags = __fmtfl;
return __old;
}
inline fmtflags
flags(fmtflags __fmtfl)
{
fmtflags __old = _M_flags;
_M_flags = __fmtfl;
return __old;
}其中_M_flags是ios_base的一个成员,保存流的一些配置信息,比如是否采用16进制输出,是否左对齐等等。可以看出,setf仅仅是将一种配置信息加入原有的配置信息中,而flags是完全替换了原有的配置信息。同时,也提供了unsetf和setf相搭配使用。如下是流的配置信息:[cpp] enum _Ios_Fmtflags
{
_S_boolalpha = 1L << 0,
_S_dec = 1L << 1,
_S_fixed = 1L << 2,
_S_hex = 1L << 3,
_S_internal = 1L << 4,
_S_left = 1L << 5,
_S_oct = 1L << 6,
_S_right = 1L << 7,
_S_scientific = 1L << 8,
_S_showbase = 1L << 9,
_S_showpoint = 1L << 10,
_S_showpos = 1L << 11,
_S_skipws = 1L << 12,
_S_unitbuf = 1L << 13,
_S_uppercase = 1L << 14,
_S_adjustfield = _S_left | _S_right | _S_internal,
_S_basefield = _S_dec | _S_oct | _S_hex,
_S_floatfield = _S_scientific | _S_fixed,
_S_ios_fmtflags_end = 1L << 16
};
enum _Ios_Fmtflags
{
_S_boolalpha = 1L << 0,
_S_dec = 1L << 1,
_S_fixed = 1L << 2,
_S_hex = 1L << 3,
_S_internal = 1L << 4,
_S_left = 1L << 5,
_S_oct = 1L << 6,
_S_right = 1L << 7,
_S_scientific = 1L << 8,
_S_showbase = 1L << 9,
_S_showpoint = 1L << 10,
_S_showpos = 1L << 11,
_S_skipws = 1L << 12,
_S_unitbuf = 1L << 13,
_S_uppercase = 1L << 14,
_S_adjustfield = _S_left | _S_right | _S_internal,
_S_basefield = _S_dec | _S_oct | _S_hex,
_S_floatfield = _S_scientific | _S_fixed,
_S_ios_fmtflags_end = 1L << 16
};对于hex操作,举个例子:[cpp] #include

using namespace std;

int main (int argc, const char * argv[])
{
cout.setf(ios::hex);
cout << 15 << endl;

return 0;
}
#include

using namespace std;

int main (int argc, const char * argv[])
{
cout.setf(ios::hex);
cout << 15 << endl;

return 0;
}程序输出:
[cpp] 15
15
setf并没有起到让输出流按照十六进制输出的作用,而如果使用cout << hex << 15 << endl; 就能够达到效果,为什么呢?
先看看cout << hex实际调用的hex函数的定义:

[cpp] inline ios_base&
hex(ios_base& __base)
{
__base.setf(ios_base::hex, ios_base::basefield);
return __base;
}
inline ios_base&
hex(ios_base& __base)
{
__base.setf(ios_base::hex, ios_base::basefield);
return __base;
}可以看出,它和cout.setf(ios::hex);是不一致的。

看看,hex函数内部调用的setf函数的定义:

[cpp] inline fmtflags
setf(fmtflags __fmtfl, fmtflags __mask)
{
fmtflags __old = _M_flags;
_M_flags &= ~__mask;
_M_flags |= (__fmtfl & __mask);
return __old;
}

_S_basefield = _S_dec | _S_oct | _S_hex,
inline fmtflags
setf(fmtflags __fmtfl, fmtflags __mask)
{
fmtflags __old = _M_flags;
_M_flags &= ~__mask;
_M_flags |= (__fmtfl & __mask);
return __old;
}

_S_basefield = _S_dec | _S_oct | _S_hex,
static const fmtflags basefield = _S_basefield;可以看出, _M_flags &=