1.区别
cout实际上是一个iostream类的对象,每次调用的时候就会输出对应的字符串,调用的实际上就是成员运算符函数operator<<,当然这里还有一个问题就是:为什么实际上我们的cout可以接受不同类型的数据并进行输出呢?
原因也很简单,就是因为我们在重载运算符的时候,也重载了多个该函数,因为标准库的作者们早就为使用者定制了iostream::operator<<对于各种C++基本数据类型的重载版本,这才使得我们在使用的时候变得如此地方便。
我们都知道,在printf中的\n可以实现一个换行,但是在C++中教程总是有意无意地让我们使用endl,两者看上去似乎一样,但是真的一样吗?
endl实际上是一个操纵符,不仅仅实现了换行的操作,而且还对输出缓冲区进行刷新(使用缓冲区的原因是为了减少硬盘灯存储设备的读写次数),实际上,对于每一个输出流,都管理一个缓冲区(也就是说在系统中是存在多个缓冲区的)
有了缓冲机制,操作系统就可以将程序的多个输出操作组合成单一的系统级写操作,(在系统中,很多读写操作并不是一定都会输出,而是存储在缓冲区上的,由于设备的写操作可能很耗时,因此允许操作系统将多个输出操作组合为单一的设备写操作可以带来很大的性能提升。)
那这里有一个问题,那我们很多的cout实际上是没有用endl或者flush等操纵符来主动清空缓冲区的,那么为什么还可以输出呢?
其实,不仅仅是这些操纵符可以控制cout来清空缓冲区,实际上,有多种方法可以清空缓冲区:
因为cout是行缓冲的,所以其实有以下几种方式(我们需要知道的是,下面任何会清空缓冲区的条件中都的确会导致输出,但是仅仅表明是在该条语句要清空缓冲区之间的某一时间点会导致输出,但是并没有说是具体什么时间点,具体时间点可能依据操作系统和具体编译环境而定):
1、缓冲区满;
2、用户手动刷新,即显示地清空,比如像上面的使用操纵符的方式;
3、程序结束(这种情况非常常见),见下面例1代码;
4、程序的下一步将要从标准输入流读入数据,则会将之前的缓冲区清空
实际上,endl是作为一个操纵符存在的,它不仅仅实现了换行操作,而且还对输出缓冲区进行了刷新,也就是说实际上,在本来的输出操作之后,endl在实现了换行的同时将缓冲区显式地清空了。
2.四种cast的使用
1.const_cast 用于修改类型的const或volatile属性,一般用于强制消除对象的常量性,c中不提供消除这const的机制
2.static_cast 该转换和c风格的转换很类似,没有运行时类型检查,所以无法保证转换的安全性。主要有以下几种用法:
(1)用于基本数据类型,或者non_const到const(反过来必须用const_cast)
(2)把空指针转换为目标类型的指针
(3)将任何类型的表达式转换为void类型
(4)可以将子类类型的指针转换为父类类型的指针(这种转换的安全性需要开发人员来保证)
3.dyminic_cast 他只用于对象和引用,主要用于执行安全的向下转型,他可以将指向子类的父类指针转换为子类指针,但是要求父类有虚函数,如果转换为指针类型失败则返回NULL,如果是引用类型转换失败则跑出bad_cast的异常
4.reinpreter_cast type_id可以是指针,引用,算术类型,函数指针或者成员指针,这个操作符可以在非相关的类型之间转换,操作只是简单的从一个指针到别的指针的值得二进制拷贝,在类型之间指向的内容不作任何类型的检查和转换。