C++标准和C++标准库
声明:整理自百度文库和网上博客文章
C语言标准
写在前面:K&R C不用说。个人以为,我们平常说的标准C,指的是ANSI C,ISO C,C89,C90。
1978年,丹尼斯•里奇(Dennis Ritchie)和布莱恩•柯林汉(Brian Kernighan)合作出版了《C程序设计语言》的第一版。书中介绍的C语言标准也被C语言程式设计师称作“K&R C”,第二版的书中也包含了一些ANSI C的标准。K&R C主要介绍了以下特色:
- 结构(struct)类型
- 长整数(long int)类型
- 无符号整数(unsigned int)类型
- 把运算符=+和=-改为+=和-=。因为=+和=-会使得编译器不知道使用者要处理i = -10还是i =- 10,使得处理上产生混淆。
即使在后来ANSI C标准被提出的许多年后,K&R C仍然是许多编译器的最低标准要求,许多老旧的编译仍然运行K&R C的标准。
C 的第一个标准是由ANSI发布的。虽然这份文档后来被国际标准化组织(ISO)采纳并且ISO发布的修订版也被ANSI采纳了,但名称ANSI C(而不是 ISO C)仍被广泛使用。ANSI C现在被几乎所有广泛使用的编译器支持。现在多数C代码是在ANSI C基础上写的。
1983年,美国国家标准协会组成了一个委员会,X3J11,为了创立 C 的一套标准。经过漫长而艰苦的过程,该标准于1989年完成,并在作为ANSI X3.159-1989 "Programming Language C"正式生效。这个版本的语言经常被称作"ANSI C",或有时称为"C89"(为了区别C99)。 在1990年,ANSI C标准(带有一些小改动)被美国国家标准协会采纳为ISO/IEC 9899:1990。这个版本有时候称为C90或者ISO C。因此,C89和C90通常指同一种语言。 传统C语言到ANSI/ISO标准C语言的改进包括:
- 增加了真正的标准库
- 新的预处理命令与特性
- 函数原型允许在函数申明中指定参数类型
- 一些新的关键字,包括 const、volatile 与 signed 宽字符、宽字符串与字节多字符
- 对约定规则、声明和类型检查的许多小改动与澄清
2000年3月,ANSI 采纳了 ISO/IEC 9899:1999 标准。这个标准通常指C99。 C99新增了一些特性,如:
- 支持不定长的数组,即数组长度可以在运行时决定。
- 变量声明不必放在语句块的开头,for 语句提倡写成 for(int i=0;i<100;++i) 的形式,即i 只在 for 语句块内部有效。
- 初始化结构的时候允许对特定的元素赋值。
- 允许编译器化简非常数的表达式。
- 取消了函数返回类型默认为 int 的规定。
但是各个公司对C99的支持所表现出来的兴趣不同。当GCC和其它一些商业编译器支持C99的大部分特性的时候,微软和Borland却似乎对此不感兴趣,他们把更多的精力放在了C++上。
在2011年12月,ANSI 采纳了 ISO/IEC 9899:2011 标准。这个标准通常即C++11。
最新的C++标准。
C++标准库分类
C++标准库的所有头文件都没有扩展名。C++标准库的内容总共在50个标准头文件中定义,其中18个提供了C库的功能。<cname>形式的标准头文件【<complex>例外】其内容与ISO标准C包含的name.h头文件相同,但容纳了C++扩展的功能。在<cname>形式标准的头文件中,与宏相关的名称在全局作用域中定义,其他名称在std命名空间中声明。在C++中还可以使用name.h形式的标准C库头文件名。
C++标准库的内容分为10类:
C1.语言支持
C2.输入/输出
C3.诊断
C4.一般工具
C5.字符串
C6.容器
C7.迭代器支持
C8.算法
C9.数值操作
C10.本地化
C1 标准库中与语言支持功能相关的头文件
<cstddef> 定义宏NULL和offsetof,以及其他标准类型size_t和ptrdiff_t。与对应的标准C头文件的区别是,NULL是C++空指针常量的补充定义,宏offsetof接受结构或者联合类型参数,只要他们没有成员指针类型的非静态成员即可。
<limits> 提供与基本数据类型相关的定义。例如,对于每个数值数据类型,它定义了可以表示出来的最大值和最小值以及二进制数字的位数。
<climits> 提供与基本整数数据类型相关的C样式定义。这些信息的C++样式定义在<limits>中
<cfloat> 提供与基本浮点型数据类型相关的C样式定义。这些信息的C++样式定义在<limits>中
<cstdlib> 提供支持程序启动和终止的宏和函数。这个头文件还声明了许多其他杂项函数,例如搜索和排序函数,从字符串转换为数值等函数。它与对应的标准C头文件stdlib.h不同,定义了abort(void)。abort()函数还有额外的功能,它不为静态或自动对象调用析构函数,也不调用传给atexit()函数的函数。它还定义了exit()函数的额外功能,可以释放静态对象,以注册的逆序调用用atexit()注册的函数。清除并关闭所有打开的C流,把控制权返回给主机环境。
<new> 支持动态内存分配
<typeinfo> 支持变量在运行期间的类型标识
<exception> 支持异常处理,这是处理程序中可能发生的错误的一种方式
<cstdarg> 支持接受数量可变的参数的函数。即在调用函数时,可以给函数传送数量不等的数据项。它定义了宏va_arg、va_end、va_start以及va_list类型
<csetjmp> 为C样式的非本地跳跃提供函数。这些函数在C++中不常用
<csignal> 为中断处理提供C样式支持
C2 支持流输入/输出的头文件
< iostream> 支持标准流cin、cout、cerr和clog的输入和输出,它还支持多字节字符标准流wcin、wcout、wcerr和wclog。
<iomanip> 提供操纵程序,允许改变流的状态,从而改变输出的格式。
<ios> 定义iostream的基类
<istream> 为管理输出流缓存区的输入定义模板类
<ostream> 为管理输出流缓存区的输出定义模板类
<sstream> 支持字符串的流输入输出
<fstream> 支持文件的流输入输出
<iosfwd> 为输入输出对象提供向前的声明
<streambuf> 支持流输入和输出的缓存
<cstdio> 为标准流提供C样式的输入和输出
<cwchar> 支持多字节字符的C样式输入输出
C3 与诊断功能相关的头文件
<stdexcept> 定义标准异常。异常是处理错误的方式
<cassert> 定义断言宏,用于检查运行期间的情形
<cerrno> 支持C样式的错误信息
C4 定义工具函数的头文件
<utility> 定义重载的关系运算符,简化关系运算符的写入,它还定义了pair类型,该类型是一种模板类型,可以存储一对值。这些功能在库的其他地方使用
<functional> 定义了许多函数对象类型和支持函数对象的功能,函数对象是支持operator()()函数调用运算符的任意对象
<memory> 给容器、管理内存的函数和auto_ptr模板类定义标准内存分配器
<ctime> 支持系统时钟函数
C5 支持字符串处理的头文件
<string> 为字符串类型提供支持和定义,包括单字节字符串(由char组成)的string和多字节字符串(由wchar_t组成)
<cctype> 单字节字符类别
<cwctype> 多字节字符类别
<cstring> 为处理非空字节序列和内存块提供函数。这不同于对应的标准C库头文件,几个C样式字符串的一般C库函数被返回值为const和非const的函数对替代了
<cwchar> 为处理、执行I/O和转换多字节字符序列提供函数,这不同于对应的标准C库头文件,几个多字节C样式字符串操作的一般C库函数被返回值为const和非const的函数对替代了。
<cstdlib> 为把单字节字符串转换为数值、在多字节字符和多字节字符串之间转换提供函数
C6 定义容器类的模板的头文件
<vector> 定义vector序列模板,这是一个大小可以重新设置的数组类型,比普通数组更安全、更灵活
<list> 定义list序列模板,这是一个序列的链表,常常在任意位置插入和删除元素
<deque> 定义deque序列模板,支持在开始和结尾的高效插入和删除操作
<queue> 为队列(先进先出)数据结构定义序列适配器queue和priority_queue
<stack> 为堆栈(后进先出)数据结构定义序列适配器stack
<map> map是一个关联容器类型,允许根据键值是唯一的,且按照升序存储。multimap类似于map,但键不是唯一的。
<set> set是一个关联容器类型,用于以升序方式存储唯一值。multiset类似于set,但是值不必是唯一的。
<bitset> 为固定长度的位序列定义bitset模板,它可以看作固定长度的紧凑型bool数组
C7 支持迭代器的头文件
<iterator> 给迭代器提供定义和支持
C8 有关算法的头文件
<algorithm> 提供一组基于算法的函数,包括置换、排序、合并和搜索
<cstdlib> 声明C标准库函数bsearch()和qsort(),进行搜索和排序
<ciso646> 允许在代码中使用and代替&&
C9 有关数值操作的头文件
<complex> 支持复杂数值的定义和操作
<valarray> 支持数值矢量的操作
<numeric> 在数值序列上定义一组一般数学操作,例如accumulate和inner_product
<cmath> 这是C数学库,其中还附加了重载函数,以支持C++约定
<cstdlib> 提供的函数可以提取整数的绝对值,对整数进行取余数操作
C10 有关本地化的头文件
<locale> 提供的本地化包括字符类别、排序序列以及货币和日期表示。
<clocale> 对本地化提供C样式支持
C++标准库与STL的关系 1
STL即标准模板库(Standard Template Library),它包括五大类组件:算法、容器、迭代器、函数对象、适配器。
STL是C++标准库的一部分,但不是全部。C++标准库是std名字空间中的所有内容,就是那些不带.h的头文件,如<cstdio>、<iostream>。如std::string,及IO流都不属于STL,但它们是STL兼容的,可以应用迭代器,算法等。虽然std::string和IO流也是模板类,但并不属于STL。
STL的实现,如STLPort中包括了IO流,string类等,其实不能确切的称为STL实现,而是比STL更大的库实现。但是某些STL类没有在标准库中实现,如hash map,STLPort中实现了。C++标准库包含一个STL的实现,但该实现是标准STL的子集。
C/C++标准库主要包含3部分: STL、IO流及本地化、C的函数库。
标准库不是STL,STL是标准模板库,是标准库的一个子集。它是一个可复用的组件库,其中包含了很多实用的算法和数据结构。stl是一个泛型思维的集中体现。
C++标准库与STL的关系 2
STL即标准模板库(Standard Template Library),它包括五大类组件:算法、容器、迭代器、函数对象、适配器。
STL是C++标准库的一部分,但不是全部。C++标准库是std名字空间中的所有内容,就是那些不带.h的头文件,如<cstdio>、<iostream>。如std::string,及IO流都不属于STL,但它们是STL兼容的,可以应用迭代器,算法等。虽然std::string和IO流也是模板类,但并不属于STL。
STL的实现,如STLPort中包括了IO流,string类等,其实不能确切的称为STL实现,而是比STL更大的库实现。但是某些STL类没有在标准库中实现,如hash map,STLPort中实现了。C++标准库包含一个STL的实现,但该实现是标准STL的子集。
STL是最新的C++标准函数库中的一个子集,这个庞大的子集占据了整个库的大约80%的分量。而作为在实现STL过程中扮演关键角色的模板则充斥了几乎整个C++标准函数库。在这里,我们有必要看一看C++标准函数库里包含了哪些内容,其中又有哪些是属于标准模板库(即STL)的。
C++标准函数库为C++程序员们提供了一个可扩展的基础性框架。我们从中可以获得极大的便利,同时也可以通过继承现有类,自己编制符合接口规范的容器、算法、迭代子等方式对之进行扩展。它大致包含了如下几个组件:
C标准函数库,基本保持了与原有C语言程序库的良好兼容,尽管有些微变化。人们总会忍不住留恋过去的美好岁月,如果你曾经是一个C程序员,对这一点一定体会颇深。或许有一点会让你觉得奇怪,那就是在C++标准库中存在两套C的函数库,一套是带有.h扩展名的(比如<stdio.h>),而另一套则没有(比如<cstdio>)。它们确实没有太大的不同。
语言支持(language support)部分,包含了一些标准类型的定义以及其他特性的定义,这些内容,被用于标准库的其他地方或是具体的应用程序中。
诊断(diagnostics)部分,提供了用于程序诊断和报错的功能,包含了异常处理(exception handling),断言(assertions),错误代码(error number codes)三种方式。
通用工具(general utilities)部分,这部分内容为C++标准库的其他部分提供支持,当然你也可以在自己的程序中调用相应功能。比如:动态内存管理工具,日期/时间处理工具。记住,这里的内容也已经被泛化了(即采用了模板机制)。
字符串(string)部分,用来代表和处理文本。它提供了足够丰富的功能。事实上,文本是一个string对象,它可以被看作是一个字符序列,字符类型可能是char,或者wchar_t等等。string可以被转换成char*类型,这样便可以和以前所写的C/C++代码和平共处了。因为那时侯除了char*,没有别的。
国际化(internationalization)部分,作为OOP特性之一的封装机制在这里扮演着消除文化和地域差异的角色,采用locale和facet可以为程序提供众多国际化支持,包括对各种字符集的支持,日期和时间的表示,数值和货币的处理等等。毕竟,在中国和在美国,人们表示日期的习惯是不同的。
容器(containers)部分,STL的一个重要组成部分,涵盖了许多数据结构,比如前面曾经提到的链表,还有:vector(类似于大小可动态增加的数组)、queue(队列)、stack(堆栈)……。string也可以看作是一个容器,适用于容器的方法同样也适用于string。现在你可以轻松的完成数据结构课程的家庭作业了。
算法(algorithms)部分,STL的一个重要组成部分,包含了大约70个通用算法,用于操控各种容器,同时也可以操控内建数组。比如:find用于在容器中查找等于某个特定值的元素,for_each用于将某个函数应用到容器中的各个元素上,sort用于对容器中的元素排序。所有这些操作都是在保证执行效率的前提下进行的,所以,如果在你使用了这些算法之后程序变得效率低下,首先一定不要怀疑这些算法本身,仔细检查一下程序的其他地方。
迭代器(iterators)部分,STL的一个重要组成部分,如果没有迭代器的撮合,容器和算法便无法结合的如此完美。事实上,每个容器都有自己的迭代器,只有容器自己才知道如何访问自己的元素。它有点像指针,算法通过迭代器来定位和操控容器中的元素。
数值(numerics)部分,包含了一些数学运算功能,提供了复数运算的支持。
输入/输出(input/output)部分,就是经过模板化了的原有标准库中的iostream部分,它提供了对C++程序输入输出的基本支持。在功能上保持了与原有iostream的兼容,并且增加了异常处理的机制,并支持国际化(internationalization)。
总体上,在C++标准函数库中,STL主要包含了容器、算法、迭代器。string也可以算做是STL的一部分。
C++标准库与STL的关系 示意图


浙公网安备 33010602011771号