《2022年C++编程对缓冲区的理解 .pdf》由会员分享,可在线阅读,更多相关《2022年C++编程对缓冲区的理解 .pdf(18页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、深圳汇众教育http:/深圳汇众教育http:/C+编程对 缓冲区的理解什么是缓冲区缓冲区又称为缓存,它是内存空间的一部分。也就是说, 在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区。缓冲区根据其对应的是输入设备还是输出设备,分为输入缓冲区和输出缓冲区。为什么要引入缓冲区我们为什么要引入缓冲区呢? 比如我们从磁盘里取信息,我们先把读出的数据放在缓冲区,计算机再直接从缓冲区中取数据, 等缓冲区的数据取完后再去磁盘中读取,这样就可以减少磁盘的读写次数,再加上计算机对缓冲区的操作大大快于对磁盘的操作,故应用缓冲区可大大提高计算机的运行速度。又比如
2、, 我们使用打印机打印文档,由于打印机的打印速度相对较慢,我们先把文档输出到打印机相应的缓冲区,打印机再自行逐步打印,这时我们的CPU 可以处理别的事情。现在您基本明白了吧,缓冲区就是一块内存区,它用在输入输出设备和CPU 之间,用来缓存数据。它使得低速的输入输出设备和高速的CPU 能够协调工作,避免低速的输入输出设备占用CPU ,解放出 CPU ,使其能够高效率工作。缓冲区的类型缓冲区分为三种类型:全缓冲、行缓冲和不带缓冲。1、全缓冲在这种情况下,当填满标准I/O 缓存后才进行实际I/O 操作。全缓冲的典型代表是对磁盘文件的读写。2、行缓冲在这种情况下,当在输入和输出中遇到换行符时,执行真正
3、的I/O 操作。这时,我们输入的字符先存放在缓冲区,等按下回车键换行时才进行实际的I/O 操作。 典型代表是键盘输入数据。3、不带缓冲名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 1 页,共 18 页 - - - - - - - - - 深圳汇众教育http:/深圳汇众教育http:/也就是不进行缓冲,标准出错情况stderr 是典型代表,这使得出错信息可以直接尽快地显示出来。缓冲区的刷新下列情况会引发缓冲区的刷新: 1、缓冲区满时 ; 2、执行 flush 语句 ; 3、执行 e
4、ndl 语句 ; 4、关闭文件。可见,缓冲区满或关闭文件时都会刷新缓冲区,进行真正的I/O 操作。另外,在C+中,我们可以使用flush 函数来刷新缓冲区(执行 I/O 操作并清空缓冲区),如:cout endl 控制符的作用是将光标移动到输出设备中下一行开头处,并且清空缓冲区。coutENDL; 相当于cout”n” FLUSH; 通过实例演示说明1、文件操作演示全缓冲创建一个控制台工程,输入如下代码:#include using namespace std; int main() 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - -
5、- 名师精心整理 - - - - - - - 第 2 页,共 18 页 - - - - - - - - - 深圳汇众教育http:/深圳汇众教育http:/ 并打开ofstream outfile(test.txt); /向 test.txt 文件中写入4096 个字符 afor(int n=0;n4096;n+) outfilea; /暂停,按任意键继续system(PAUSE); /继续向 test.txt 文件中写入字符b,也就是说,第4097 个字符是 boutfilerun(); / 根据 vehicle 的具体类型调用对应的run() int main() Car car; Air
6、plane airplane; run_vehicle(&car); / 调用 Car:run() run_vehicle(&airplane); / 调用 Airplane:run() 此例中, 关键的多态接口元素为虚函数run() 。由于 run_vehicle() 的参数为指向基类Vehicle 的指针,因而无法在编译期决定使用哪一个版本的run() 。在运行期,为了分派函数调用,虚函数被调用的那个对象的完整动态类型将被访问。这样一来,对一个Car 对象调用 run_vehicle() ,实际上将调用Car:run() ,而对于 Airplane 对象而言将调用Airplane:run(
7、)。或许动态多态最吸引人之处在于处理异质对象集合的能力:/ dynamic_poly_2.cpp #include #include #include dynamic_poly.h / run 异质 vehicles 集合名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 8 页,共 18 页 - - - - - - - - - 深圳汇众教育http:/深圳汇众教育http:/void run_vehicles(const std:vector& vehicles) for (unsig
8、ned int i = 0; i run(); / 根据具体 vehicle 的类型调用对应的run() int main() Car car; Airplane airplane; std:vector v; / 异质 vehicles 集合v.push_back(&car); v.push_back(&airplane); run_vehicles(v); / run 不同类型的vehicles 在 run_vehicles()中, vehiclesi-run()依据正被迭代的元素的类型而调用不同的成员函数。这从一个侧面体现了面向对象编程风格的优雅。静态多态如果说动态多态是通过虚函数来表达
9、共同接口的话,那么静态多态则是通过“ 彼此单独定义但支持共同操作的具体类” 来表达共同性,换句话说,必须存在必需的同名成员函数。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 9 页,共 18 页 - - - - - - - - - 深圳汇众教育http:/深圳汇众教育http:/我们可以采用静态多态机制重写上一节的例子。这一次,我们不再定义vehicles 类层次结构, 相反,我们编写彼此无关的具体类Car 和 Airplane( 它们都有一个run() 成员函数 ):/ stat
10、ic_poly.h #include /具体类 Car class Car public: void run() const std:cout run a carn; ; /具体类 Airplane class Airplane public: void run() const std:cout run a airplanen; ; 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 10 页,共 18 页 - - - - - - - - - 深圳汇众教育http:/深圳汇众教育http
11、:/run_vehicle()应用程序被改写如下:/ static_poly_1.cpp #include #include #include static_poly.h / 通过引用而run 任何 vehicle template void run_vehicle(const Vehicle& vehicle) vehicle.run(); / 根据 vehicle 的具体类型调用对应的run() int main() Car car; Airplane airplane; run_vehicle(car); / 调用 Car:run() run_vehicle(airplane); / 调
12、用 Airplane:run() 现在 Vehicle 用作模板参数而非公共基类对象(事实上,这里的 Vehicle 只是一个符合直觉的记号而已,此外别无它意)。经过编译器处理后,我们最终会得到run_vehicle() 和 run_vehicle() 两个不同的函数。这和动态多态不同,动态多态凭借虚函数分派机制在运行期只有一个 run_vehicle()函数。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 11 页,共 18 页 - - - - - - - - - 深圳汇众教育ht
13、tp:/深圳汇众教育http:/我们无法再透明地处理异质对象集合了,因为所有类型都必须在编译期予以决定。不过,为不同的vehicles引入不同的集合只是举手之劳。由于无需再将集合元素局限于指针或引用,我们现在可以从执行性能和类型安全两方面获得好处:/ static_poly_2.cpp #include #include #include static_poly.h / run 同质 vehicles 集合template void run_vehicles(const std:vector& vehicles) for (unsigned int i = 0; i vehicles.size
14、(); +i) vehiclesi.run(); / 根据 vehicle 的具体类型调用相应的run() int main() Car car1, car2; Airplane airplane1, airplane2; std:vector vc; / 同质 cars 集合vc.push_back(car1); 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 12 页,共 18 页 - - - - - - - - - 深圳汇众教育http:/深圳汇众教育http:/vc.push
15、_back(car2); /vc.push_back(airplane1); / 错误:类型不匹配run_vehicles(vc); / run cars std:vector vs; / 同质 airplanes集合vs.push_back(airplane1); vs.push_back(airplane2); /vs.push_back(car1); / 错误:类型不匹配run_vehicles(vs); / run airplanes 两种多态机制的结合使用在一些高级C+应用中,我们可能需要结合使用动态多态和静态多态两种机制,以期达到对象操作的优雅、安全和高效。例如,我们既希望一致而优
16、雅地处理vehicles 的 run问题, 又希望 “ 安全而高效 ” 地完成给飞行器(飞机、 飞艇等 )进行 “ 空中加油 ” 这样的高难度动作。为此,我们首先将上面的vehicles类层次结构改写如下:/ dscombine_poly.h #include #include / 公共抽象基类Vehicle class Vehicle public: virtual void run() const = 0; 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 13 页,共 18 页
17、- - - - - - - - - 深圳汇众教育http:/深圳汇众教育http:/; / 派生于 Vehicle 的具体类 Car class Car: public Vehicle public: virtual void run() const std:cout run a carn; ; / 派生于 Vehicle 的具体类 Airplane class Airplane: public Vehicle public: virtual void run() const std:cout run a airplanen; void add_oil() const std:cout add
18、 oil to airplanen; 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 14 页,共 18 页 - - - - - - - - - 深圳汇众教育http:/深圳汇众教育http:/ ; / 派生于 Vehicle 的具体类 Airship class Airship: public Vehicle public: virtual void run() const std:cout run a airshipn; void add_oil() const std:cout
19、 add oil to airshipn; ; 我们理想中的应用程序可以编写如下:/ dscombine_poly.cpp #include #include #include dscombine_poly.h / run 异质 vehicles 集合名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 15 页,共 18 页 - - - - - - - - - 深圳汇众教育http:/深圳汇众教育http:/void run_vehicles(const std:vector& vehi
20、cles) for (unsigned int i = 0; i run(); / 根据具体的vehicle 类型调用对应的run() / 为某种特定的aircrafts 同质对象集合进行“ 空中加油 ”template void add_oil_to_aircrafts_in_the_sky(const std:vector& aircrafts) for (unsigned int i = 0; i aircrafts.size(); +i) aircraftsi.add_oil(); int main() Car car1, car2; Airplane airplane1, airpl
21、ane2; Airship airship1, airship2; 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 16 页,共 18 页 - - - - - - - - - 深圳汇众教育http:/深圳汇众教育http:/std:vector v; / 异质 vehicles 集合v.push_back(&car1); v.push_back(&airplane1); v.push_back(&airship1); run_vehicles(v); / run 不同种类的vehic
22、les std:vector vp; / 同质 airplanes集合vp.push_back(airplane1); vp.push_back(airplane2); add_oil_to_aircrafts_in_the_sky(vp); / 为 airplanes进行 “ 空中加油 ”std:vector vs; / 同质 airships集合vs.push_back(airship1); vs.push_back(airship2); add_oil_to_aircrafts_in_the_sky(vs); / 为 airships 进行 “ 空中加油 ” 我们保留了类层次结构,目的是
23、为了能够利用run_vehicles()一致而优雅地处理异质对象集合 vehicles 的 run 问题。 同时,利用函数模板add_oil_to_aircrafts_in_the_sky(),我们仍然可以处理特定种类的vehicles aircrafts( 包括 airplanes 和airships) 的“ 空中加油 ” 问题。其中,我们避开使用指针,从而在执行性能和类型安全两方面达到了预期目标。结语长期以来, C+社群对于多态的内涵和外延一直争论不休。在 comp.object这样的网络论坛上,此类话题争论至今仍随处可见。曾经有人将动态多态(dynamic polymorphism)称为
24、 inclusion polymorphism ,而将静态多态(static polymorphism)称为 parametric polymorphism 或 parameterized polymorphism 。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 17 页,共 18 页 - - - - - - - - - 深圳汇众教育http:/深圳汇众教育http:/我注意到2003 年斯坦福大学公开的一份C+ and Object-Oriented Programming教案中
25、明确提到了函数多态概念:Function overloading is also referred to as function polymorphism as it involves one function having many forms 。 文后的 “ 参考文献 ” 单元给出了这个网页链接。可能你是第一次看到宏多态(macro polymorphism)这个术语。不必讶异 也许我就是造出这个术语的“ 第一人 ” 。显然,带变量的宏(或类似于函数的宏或伪函数宏)的替换机制除了免除小型函数的调用开销之外,也表现出了类似的多态性。在我们上面的例子中,字符串相加所表现出来的符合直觉的连接操作
26、,事实上是由底部运算符重载机制(operator overloading) 支持的。值得指出的是,C+社群中有人将运算符重载所表现出来的多态称为ad hoc polymorphism 。David Vandevoorde和 Nicolai M. Josuttis 在他们的著作C+ Templates: The Complete Guide 一书中系统地阐述了静态多态和动态多态技术。因为认为 “ 和其他语言机制关系不大 ” ,这本书没有提及“ 宏多态 ”(以及 “ 函数多态 ”)。(需要说明的是,笔者本人是这本书的繁体中文版译者之一,本文正是基于这本书的第14 章 The Polymorphic
27、 Power of Templates 编写而成 ) 动态多态只需要一个多态函数,生成的可执行代码尺寸较小,静态多态必须针对不同的类型产生不同的模板实体,尺寸会大一些, 但生成的代码会更快,因为无需通过指针进行间接操作。 静态多态比动态多态更加类型安全,因为全部绑定都被检查于编译期。正如前面例子所示,你不可将一个错误的类型的对象插入到从一个模板实例化而来的容器之中。此外,正如你已经看到的那样,动态多态可以优雅地处理异质对象集合,而静态多态可以用来实现安全、高效的同质对象集合操作。静态多态为C+带来了泛型编程(generic programming)的概念。泛型编程可以认为是“ 组件功能基于框架
28、整体而设计” 的模板编程。 STL 就是泛型编程的一个典范。STL 是一个框架,它提供了大量的算法、容器和迭代器,全部以模板技术实现。从理论上讲,STL 的功能当然可以使用动态多态来实现,不过这样一来其性能必将大打折扣。静态多态还为C+ 社群带来了泛型模式(generic patterns) 的概念。理论上,每一个需要通过虚函数和类继承而支持的设计模式都可以利用基于模板的静态多态技术(甚至可以结合使用动态多态和静态多态两种技术)而实现。正如你看到的那样,Andrei Alexandrescu的天才作品Modern C+ Design: Generic Programming and Design Patterns Applied(Addison-Wesley)和 Loki 程序库已经走在了我们的前面。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 18 页,共 18 页 - - - - - - - - -