10第十章 C++标准模板库
- 格式:pdf
- 大小:399.98 KB
- 文档页数:97
C++“准”标准库Boost简介标准C++的当前版本发布于1998,它为传统的面向过程编程、面向对象编程和泛型编程提供了坚实的支持。
正如旧C++(1998之前的)独力承担了把面向对象普及到日常的软件开发中一样,C++98在为泛型编程做着同样的事情。
九十年代中期标准模板库(STL)与标准C++的集成已经引起了另一次编程范式的转变,就象八十年代的时候Bjarne Stroustrup把类引入到C一样。
现在大多数的C++开发者都熟悉STL的概念,这再次提升了整体的水平。
C++能力的应用仍旧被不断发现。
今天许多的C++库,包括特殊的数学库,都大量利用了模板元编译的技术,它是设计C++模板的时候没有预测到的幸运结果。
随着C++社区里的高级工具和技术不断涌现,开发复杂应用软件正变得更简单、更令人愉快。
很难描述Boost对于C++世界的重要性。
自从C++98发布后,除了ISO的标准C++委员会,没有一个团体对于C++的发展方向有比Boost更大的影响(许多Boost的成员本身就是WG21的重要成员,包括它的创始人,我的朋友Beman Dawes)。
成千上万个杰出的Boost志愿者无私地,以对等审查方式开发了许多C++98没有提供的很有用的库。
这些库中的十个已被接受将加入到即将到来的C++0x的库中,更多的库正被考虑接受。
Where a library approach has been shown to be wanting,the wisdom gained from the cross-pollination of Boost and WG21 has suggested a few modest language enhancements,which are now being entertained.你不太可能没有听说过Boost,我来问一下你…你需要在文本和数字之间进行转换,或在任意的可流处理的类之间进行转换?没有问题,用Boost.lexical_cast。
标准模板库-------------------siwuxie095在长期的编码中,聪明的程序员们发现:有⼀些代码经常碰到,⽽且需求特别稳定,于是,各⼤公司在出售⾃⼰的 IDE 环境时,就会把这些模板代码打包,⼀起销售慢慢地,这些⼤公司之间就达成了某种共识,觉得应该把这些涉及模板的通⽤代码进⼀步的统⼀和规范,于是,⼤家慢慢形成了⼀套 C++ 的标准模板,就是现在所看到的标准模板库标准模板库标准模板库,即 Standard Template Lib,简称为 STL标准模板库所涉及的内容⾮常多,⽆法⼀⼀列举,这⾥只介绍其中具有代表性的、最常⽤的部分(1)向量 vector向量,多么⾼⼤上的名字,⼤家千万不要被它的名字所吓倒就其本质来说,向量就是对数组的封装⼤家可以把它看做是⼀个数组,只不过相对于此前所学的传统数组,向量这个数组的功能要强⼤的多,它可以根据存储的元素个数⾃动的变长或缩短,并且它具有⼀个很优秀的特点,即能够在随机读取数据的时候,在常数时间内完成,这是⾮常不容易的也就是说,⽆论这个向量中是存⼗个数据,还是存⼀万个数据,它都能够很快的从中找出我们想要的数据向量的初始化或定义的⽅法,常⽤的有 4 种:在使⽤时:第⼀⾏代码使⽤的是第⼀种初始化的⽅法,初始化了⼀个空的向量 ivec1,第⼆⾏代码是⽤空的向量 ivec1 ⼜去初始化了另外⼀个空的向量 ivec2第三⾏和第四⾏代码,同理 … 只不过参数不同罢了第五⾏代码是⽤10个-1数字初始化 ivec4,⽽第六⾏代码则是⽤10个hi!字符串来初始化 svec向量初始化之后必须要有⼀些配套的使⽤⽅法,这样程序员才能真正体会到标准模板所带来的⽅便,如下:在使⽤时:就像通过类模板去实例化⼀个模板类时⼀样,需要在 vector 后⾯的尖括号中传⼊⼀个参数,这⾥是 int,后⾯就是对象 vec 了vec 调⽤push_back() 时,就会在当前向量的尾部插⼊元素 10,⽽调⽤pop_back()就会将这个 10 抹掉,最后打印vec.size()即总共数据的个数为 0对于数组来说,遍历数组是⼀种⾮常常见的操作,⽽对于向量来说,遍历时可以像数组⼀样去遍历它,如下:除了上⾯的遍历⽅法之外,还有⼀个常⽤的遍历⽅法,即⽤迭代器来进⾏遍历迭代器,即iterator,通过它就可以访问标准模板库对象⾥的每⼀个元素如:通过迭代器去遍历向量中的每⼀个元素将向量定义为 vec,通过 vec 的push_back() 向向量中压⼊很多的元素,并依次放在向量的尾部,当然,第⼀次调⽤时,会放在第⼀个元素上 …向量迭代器的定义⽅法:在 vector 后⾯的尖括号中标记出当前的向量所使⽤的数据类型,再接⼀对冒号::,⽤它来标记出当前的迭代器是属于向量的迭代器,然后是迭代器 citer,即 citer 的数据类型是vector<string>::iterator,然后通过迭代器 citer 来指向当前向量 vec 的第⼀个元素,最后⽤ for 循环就可以⽤迭代器 citer 去遍历整个向量了遍历的⽅法很有意思:1)⾸先作为 for 循环来说,第⼀个条件可以什么都不写2)第⼆个条件,即 for 循环的截⽌条件是citer != vec.end(),其中end() 表⽰当前向量 vec 的最后⼀个元素的下⼀个位置,显然,这是合理的3)第三个条件citer++表明:citer 作为迭代器来说,是可以通过 ++来进⾏修饰的,它的意义就相当于通过⼀个指针⼜指向了向量的下⼀个元素,既然可以++,⾃然也可以--,即指向向量的上⼀个元素4)要打印当前迭代器所指向的向量的值,切记要在迭代器 citer 前加⼀个 *,这样,就指的是当前迭代器所指向的元素本⾝了(2)链表 list链表的本质,即它的数据结构,如下:链表⼀般由若⼲结点组成,如果⼀个结点都没有,称之为空链表,如果有多个结点,把第⼀个结点称之为头结点对于每⼀个结点来说,⼜由两部分组成:⼀部分是数据部分,也叫做数据域,另⼀部分是指针部分,也叫做指针域,指针部分⽤来将各个结点串联起来有⼀种链表叫双链表,即不仅可以从头找到尾,还可以从尾找到头对于链表来说,如果它想插⼊⼀个数据,如:在 D 和 E 之间插⼊数据,可以让 D 的指针域指向插⼊进来的数据,再让插⼊进来的数据的指针域指向 E可见:链表插⼊数据的操作⾮常简单,⽽向量如果想在中间插⼊⼀个数据,那么它其后的所有数据就要向后移⼀个位置,相对于链表来说,就⾮常复杂所以,对于链表来说,它的特点就是数据插⼊的速度⽐较快在使⽤⽅法上,链表与向量的使⽤⽅法基本相同,它也有 begin()、end()等等函数,并且它也可以通过迭代器进⾏遍历的访问(3)映射 map关于映射,先来看⼀下它的数据结构,如下:对于映射来说,存储的数据都是成对出现的,把它们标记为key 和value,key 称之为键,⽽ value 称之为值key 和 value 是⼀对⼀对出现的,它们往映射这种数据结构中存放时,也是⼀对⼀对去放的所以在访问时,就可以通过键来找到对应的值看如下实例:当通过映射 map 定义了⼀个对象 m 后,需要向 m 中放若⼲对key-value⽽正是通过pair来定义对,即键值对,再通过 m 调⽤insert()函数将键值对放⼊到映射当中去如果想要访问 value,就可以通过 m 接 key 的索引即可,如:通过m[10]就可以访问到shanghai,这种访问⽅式和数组很相似再看另⼀实例:与上例不同的是,key 不再是数字,⽽是字符串,通过m["S"]即可访问到shanghai程序 1:main.cpp:#include"stdlib.h"#include <iostream>#include <vector>using namespace std;int main(void){//注意向量vector是⼀个⾸字母⼩写的类型//给⼀个类的参数这⾥是int 再写变量名vector<int> vec;//从向量的尾部插⼊数据vec.push_back(3);vec.push_back(4);vec.push_back(6);//cout << vec.size() << endl;//当前数据的个数//vec.pop_back();//将尾部的数据删除(弹出)//cout << vec.size() << endl;//遍历该向量for (int i = 0; i < vec.size();i++){cout << vec[i] << endl;}//拿到向量的第⼀个元素迭代器相当于是⼀个指针通过指针指向第⼀个元素vector<int>::iterator itor = vec.begin();//cout << *itor << endl;//打印第⼀个元素//通过迭代器遍历向量//vec.end();是最后⼀个元素的下⼀个位置for (; itor != vec.end();itor++){cout << *itor << endl;}cout << endl;cout << vec.front() << endl;//取第⼀个元素cout << vec.back() << endl;//取最后⼀个元素system("pause");return0;}//向量就其本质来说其实就是数组的封装可以看做⼀个数组//只是向量这个数组相对于传统数组来说功能要强⼤的多//它可以根据存储的元素个数⾃动变长或缩短//并且具有⼀个很优秀的特点就是在能够随机读取数据的时候//在常数时间内完成(读取能在常数时间内完成)//10个或者10000个数据都能很快找出想要的数据////迭代器与类相关的如果要去迭代向量当中的每⼀个元素//就要通过向量的迭代器进⾏迭代程序 2:main.cpp:#include"stdlib.h"#include <iostream>#include <list>#include <map>#include <string>using namespace std;int main(void){list<int> list1;//链表list1.push_back(4);list1.push_back(7);list1.push_back(9);//这种遍历是错误的只能通过迭代器进⾏遍历/*for (int i = 0; i < list1.size();i++){cout << list1[i] << endl;}*/list<int>::iterator itorx = list1.begin();for (; itorx != list1.end();itorx++){cout << *itorx << endl;}cout << endl << endl;//作为映射来说存储的数据都是成对出现的前⾯的是key(键)//后⾯的是value(值)每⼀个元素都是⼀对 m是映射的对象map<int, string> m;pair<int, string> p1(3, "hello");//⼀对定义若⼲对key vallue值pair<int, string> p2(6, "world");pair<int, string> p3(9, "beijing");//映射没有 push_back() ⽅法,通过 insert() 进⾏插⼊m.insert(p1);m.insert(p2);m.insert(p3);//访问的时候通过索引加key值的⽅式即通过键来找值//若开始定义的映射是这样//map<string,string> m;//pair<string,string> p1("H","hello"); 再插⼊//访问时就可以 m["H"] 同样是通过键来找值cout << m[3] << endl;cout << m[9] << endl;cout << endl << endl;map<int, string>::iterator itor = m.begin();for (; itor != m.end();itor++){cout << itor->first << endl;//第⼀个keycout << itor->second << endl;//第⼆个valuecout << endl;//不能通过 cout<<*itor<<endl; 的⽅式访问因为作为映射来说//每⼀个元素都是⼀对也就是⼀个pair////其中包含⼀个key ⼀个value 如果直接通过*(星号)来指出这个//元素的内容的话计算机是不知道该如何输出的怎么办//必须要将key和value分别输出出来//⽅式如上}system("pause");return0;}【made by siwuxie095】。
案例库第1章绪论1。
两种药用于同一种病,A药治疗5例,4例好转;B药治疗50例,36例好转.结论是:A药优于B药。
请问其结论合理吗?为什么?应该如何?2. 某研究者为了探讨原发性高血压患者肾小管早期损害的监控指标,选取尿常规、蛋白定性检查阴性,血肌酐、尿素氮均在正常范围内的原发性高血压患者74例作为病例组,其中男43例,女31例,平均年龄61岁(40~73岁)。
根据高血压的病程将患者分为三组,Ⅰ组高血压病期<10年,Ⅱ组高血压病期10~20年,Ⅲ组高血压病期>20年。
另选取53名体检健康的职工为对照组。
观测两组尿视黄醇结合蛋白(retinal binding protein,RBP)、微量白蛋白(microalbumin,mALB)、β2微球蛋白(β2 microglobulin,β2-MG)和N-乙酰-β-D—氨基葡萄糖苷酶(N—acetyl—β—D-glucosaminidase, NAG)四项定量指标的取值。
结论为:尿RBP、mALB、β2—MG和NAG是原发性高血压患者肾小球、肾小管早期损害的敏感指标.请辨析这样设计实验存在什么问题?正确的做法是什么?3。
某研究者的论文题目为“大学生身心健康状况及其影响因素研究”,以某地职业技术学院理、工、文、医学生(三年制)为研究对象,理、工、文、医学生分别挑选了60、38、19和46人,以问卷方式调查每位学生的一般健康状况、焦虑程度、抑郁程度等.得出的结论是:“大学生身心健康状况不容乐观,学业问题、就业压力、身体状况差、人际交往不良、社会支持不力为主要影响因素”。
请问其结论合理吗?为什么?应该如何?4。
某部队共有1 200人,在某段时间内患某病的人数有120人,其中男性114人,女性6人。
某卫生员进行统计分析后说,经假设检验,该病的两性发病率(114/120=95%与6/120=5%)之间的差别有统计学意义,由此得出结论:“该病男性易得”。
你对这个结论有何看法?若结论是错误的,那么,错误的实质是什么?正确的做法是什么?第二、三、四章1.某人编制了一张统计表(表1),你认为哪些需要改进?表1 1976—1979年吉林市各型恶性肿瘤的死亡率2.某医生观察了1 402名临产母亲的住院天数(表2),并得到平均住院天数为6.6天.请对此发表评论。
C++标准模板库使用2005年8月目录一、模板简单介绍: (3)1. 函数模板 (3)2. 类模板 (4)二、STL概论 (6)三、STL的组件以及关系 (6)四、常用容器介绍 (7)1. 序列式容器 (7)1.1 Vector (7)1.2 List (16)2. 关联式容器: (22)2.1 Set (22)2.2 multiset (24)2.3 map (27)2.4 multimap (29)五、写在后面 (34)六、附录:如何选择容器 (34)一、模板简单介绍:1.函数模板请看看下面这个题目:实现一个函数,输入2个变量,输出这两个变量中值比较大的元素。
要求:此函数可以接受int、char以及double类型的参数。
对于这个问题,如果是C语言的话,估计实现会是这个样子:// 用于比较char的函数char MaxOfChar( char cNum1, char cNum2 ){return ( cNum1 > cNum2 ) ? cNum1 : cNum2;}// 用于比较int的函数int MaxOfInt( int iNum1, int iNum2 ){return ( iNum1 > iNum2 ) ? iNum1 : iNum2;}// 用于比较double的函数double MaxOfDouble( double dNum1, double dNum2 ){return ( dNum1 > dNum2 ) ? dNum1 : dNum2;}但是到了C++时代,由于存在重载的概念,所以实现起来应该是这个样子:// 用于比较char的函数char Max( char cNum1, char cNum2 ){return ( cNum1 > cNum2 ) ? cNum1 : cNum2;}// 用于比较int的函数int Max( int iNum1, int iNum2 ){return ( iNum1 > iNum2 ) ? iNum1 : iNum2;}// 用于比较double的函数double Max( double dNum1, double dNum2 ){return ( dNum1 > dNum2 ) ? dNum1 : dNum2;}对比上面两个例子,对于函数的实现来说,代码量没有什么变化,只不过函数的名字由3个变成了1个。
标准模板库标准模板库,也叫STL,是一个 C++ 容器类库,算法和迭代器。
他提供许多基本算法,数据结构。
STL 是一个通用库,即可以充份定制:几乎所有的 STL 组件都是模板。
在你使用 STL 前,你必须了解模板的工作情况。
容器和算法和许多类库一样,STL 包含容器类 - 可以包含其他对象的类。
STL 包含向量类,链表类,双向队列类,集合类,图类,等等。
他们中的每个类都是模板,能包含各种类型的对象。
例如,你可以用 vector<int> ,就象常规的 C 语言中的数组,除了 vector 不要你象数组那样考虑到动态内存分配的问题。
vector<int> v(3); // 定义一个有三个元素的向量类v[0] = 7;v[1] = v[0] + 3;v[2] = v[0] + v[1]; // v[0] == 7, v[1] == 10, v[2] == 17STL 还包含了大量的算法。
他们巧妙地处理储存在容器中的数据。
你能够颠倒vector 中的元素,只是简单使用 reverse 算法。
reverse(v.begin(), v.end()); // v[0] == 17, v[1] == 10, v[2] == 7在调用 reverse 的时候有两点要注意。
首先,他是个全局函数,而不是成员函数。
其次,他有两个参数,而不是一个:他操作一定范围的元素而不是操作容器。
在这个例子中他正好是对整个容器 V 操作。
以上两点的原因是相同的:reverse 和其他 STL 算法一样,他们是通用的,也就是说, reverse 不仅可以用来颠倒向量的元素,也可以颠倒链表中元素的顺序。
甚至可以对数组操作。
下面的程序是合法的。
double A[6] = { 1.2, 1.3, 1.4, 1.5, 1.6, 1.7 };reverse(A, A + 6);for (int i = 0; i < 6; ++i)cout << "A[" << i << "] = " << A[i];这个例子也用到了范围,和我们上面的向量的例子一样:第一个参数是指向要操作的范围的头的指针,第二个参数是指向尾的指针。
c标准文档
C标准文档是由国际标准化组织(ISO)和国际电工委员会(IEC)共同制定的,用于规范C语言编程的标准。
它包括了C语言的语法、语义、库函数等方面的规定,是C语言程序员必须遵守的规范。
C标准文档分为多个部分,其中最常使用的是C99标准。
C99标准于1999年发布,对C语言进行了一系列的改进和完善,增加了一些新的语言特性,如变长数组、复合字面量等。
此外,C99标准还对原有的语法进行了一些调整和优化,提高了代码的可读性和可维护性。
除了C99标准之外,还有一些其他的C标准文档,如C89、C11等。
这些标准的发布时间不同,对C语言的支持程度也有所不同。
一般来说,最新的标准包含更多的语言特性和更好的性能优化,因此建议使用最新版本的标准进行编程。
C标准文档是C语言编程的基础,对于学习和掌握C语言非常重要。
通过熟悉并遵守这些标准,可以提高代码的质量和效率,同时也能够更好地与其他程序员进行交流和合作。
标准库与标准模板库C++强⼤的功能来源于其丰富的类库及库函数资源。
C++标准库的内容总共在50个标准头⽂件中定义。
在C++开发中,要尽可能地利⽤标准库完成。
这样做的直接好处包括:(1)成本:已经作为标准提供,何苦再花费时间、⼈⼒重新开发呢;(2)质量:标准库的都是经过严格测试的,正确性有保证;(3)效率:关于⼈的效率已经体现在成本中了,关于代码的执⾏效率要相信实现标准库的⼤⽜们的⽔平;(4)良好的编程风格:采⽤⾏业中普遍的做法进⾏开发。
⼀、C++标准库C++标准库的内容分为10类,分别是:(⼀)语⾔⽀持;(⼆)输⼊/输出;(三)诊断;(四)⼀般⼯具;(五)字符串;(六)容器;(七)迭代器⽀持;(⼋)算法;(九)数值操作;(⼗)本地化。
(⼀)标准库中与语⾔⽀持功能相关的头⽂件(11个)头⽂件描述<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()函数的函数。