1.endl的本质
如果我们定义char c=endl;会得到一个编译错误,这说明endl并不是一个字符,所以应该到系统头文件中去查找endl的定义。
通过VS2012转到定义,找到了endl的定义如下:
template<class _Elem,class _Traits> inline basic_ostream<_Elem, _Traits>&
__CLRCALL_OR_CDECL endl(basic_ostream<_Elem, _Traits>& _Ostr)
{ // insert newline and flush stream
_Ostr.put(_Ostr.widen('\n'));
_Ostr.flush();
return (_Ostr);
}
从定义中看出,endl是一个函数模板,它实例化之后变成一个模板函数,其作用如这个函数模板的注释所示,插入换行符并刷新输出流。
(刷新输出流:将缓冲区的数据全部传递到输出设备,并将输出缓冲区清空。)
2.cout<< endl的介绍
endl是一个函数模板,再被使用时会实例化为模板函数。
但是函数调用应该使用一对圆括号,也就是写成endl()的形式,而在语句cout<<”Hello world”<<endl;
中并没有这样,原因何在?
cout对象的<<操作符接收到endl函数的地址后,会在重载的操作符函数内部调用endl函数,而endl函数会结束当前行并刷新输出缓冲区。
为了证明endl是一个 函数模板,或者说endl是一个经过隐式实例化之后的模板函数,我们把程序改造如下:
#include <iostream>
using namespace std;
int main(){
cout<<"Hello world"<<&endl;
}
这个程序可以正常运行,并且结果完全同上一个程序。
原因是对于一个函数而言,函数名本身就代表函数的入口地址,而函数名前加&也代表函数的入口地址。
3.endl其实是IO操纵符
具体内容后续追加
主要内容转载自: