1、单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,第,7,章,模板与,STL,模板(,template,)是,C+,实现代码重用机制的重要工具,是泛型技术(即与数据类型无关的通用程序设计技术)的基础。,模板是,C+,中相对较新的,语言机制,它实现了与具体数据类型无关的通用算法程序设计,能够提高软件开发的效率,是程序代码复用的强有力工具。,本章主要介绍了函数模板和类模板两类,以及,STL,库中的几个常用模板数据类型。,7.1,模板,的概念,1,、模板概念,模板是对具有相同特性的函数或类的再抽象,模板是一种参数多态性的工具,可以为逻辑功能相同而类型不同的程序提供一
2、种代码共享的机制。,一个模板并非一个实实在在的函数或类,仅仅是一个函数或类的描述,是参数化的函数和类。,2,、模板分类,函数模板,类模板,3,、实例化,instantiation,抽象,变量,类型,对象,类,函数函数模板,类类模板,实例化是抽象的逆过程,用实际数据类型代入模板,每一种不同数据类型的实例化,都将生成一份不同的代码,模板被使用前必须实例化,模板函数实例化后得到的函数叫模板函数,模板类实例化得到的类叫模板类,7.1,模板,的概念,7.1,模板的概念,模板,(函数模板或类模板),模板函数,模板类,对象,实例化,实例化,实例化,7.2,函数,模板与模板函数,函数模板提供了一种通用的函数行
3、为,该函数行为可以用多种不同的数据类型进行调用,编译器会据调用类型自动将它实例化为具体数据类型的函数代码,也就是说函数模板代表了一个函数家族。,与普通函数相比,函数模板中某些函数元素的数据类型是未确定的,这些元素的类型将在使用时被参数化;与重载函数相比,函数模板不需要程序员重复编写函数代码,它可以自动生成许多功能相同但参数和返回值类型不同的函数。,7.2,函数,模板与模板函数,1,、,引例:实现求不同数据中最大数的,max,函数方法,Macro in C,实现,#define max(x,y)(x)(y)?(x):(y),char,ch,=max(a,b);char,ch,=(a)(b)?(a
4、)(b),int,i=max(2,3);,int,i=(2)(3)?(2):(3);,float f=max(5.0,9);float f=(5.0)(9)?(5.0):(9),特点:,“自动具备多态特征”,简单的文本替代,不进行任何语法检查,不适合表达复杂的逻辑,C,实现,max,可采用如下的重载方式,实现,int,max(,int,i,int,j)return ij?i:j;,int,max(char c1,char c2)return c1c2?c1:c2;,float max(float f1,float f2)return f1f2?f1:f2;,int,i=max(3,4);,ch
5、ar,ch,=max(a,A);,float f=max(5.0,1.0);,特点:,可以进行完备的语法检查、适于描述复杂逻辑,相同逻辑重复描述,繁琐、不易扩充,7.2,函数,模板与模板函数,引例:用,C,Template,实现的,max,实现,template,T max(T a,T b)return ab?a:b;,int,i=max(3,4);,char,ch,=max(a,A);,float f=max(5.0,1.0);,特点:,可以进行完备的语法检查、适于描述复杂逻辑,相同逻辑只描述一次,针对不同类型的版本由编译器自动生成相应代码,7.2,函数模板,与模板函数,引例:实现,max,
6、Template in C,实现,template,T max(T a,T b)return ab?a:b;,int,i=max(3,4);,char,ch,=max(a,A);,float f=max(5.0,1.0);,特点:,可以进行完备的语法检查、适于描述复杂逻辑,相同逻辑只描述一次,针对不同类型的版本由编译器自动生成相应代码,7.2,函数,模板与模板函数,1,、函数模板的定义,template,返回类型 函数名,(,参数表,),/,函数模板定义体,template,是定义模板的关键字;写在一对,中的,T1,,,T2,,,是模板参数,其中的,class,表示其后的参数可以是任意类型。,
7、模板参数常称为类型参数或类属参数,在模板实例化(即调用模板函数时)时需要传递的实参是一种数据类型,如,int,或,double,之类。,函数模板的参数表中常常出现模板参数,如,T1,,,T2,7.2.1,函数,模板的定义,7.2.1,函数,模板的定义,【,例,7-1】,求两数最小值的函数模板。,/Eg7-1.cpp,#include,using namespace std;,template,T,min(T,a,T,b),return(a,b)?a:b,;,void main(),double a=2,b=3.4;,float c=2.3,d=3.2;,cout,2,,,3,的最小值是:,mi
8、n(2,3),endl,;,cout,2,,,3.4,的最小值是:,min(a,b,),endl,;,cout,a,,,b,的最小值是:,min(a,b,),endl,;,cout,2.3,,,3.2,的最小值是:,min(c,d,),endl,;,7.2.1,函数,模板的定义,2,、使用函数模板的注意事项,在定义模板时,不允许,template,语句与函数模板定义之间有任何其他语句。,template,int,x;,/,错误,不允许在此位置有任何语句,T,min(T,a,T,b),函数模板可以有多个类型参数,但每个类型参数都必须用关键字,class,或,typename,限定。此外,模板参数
9、中还可以出现确定类型参数,称为非类型参数。例:,template,T1 fx(T1 a,T 2 b,T3 c),在传递实参时,非类型参数,T4,只能使用常量,如,6,7.2.1,函数,模板的定义,不要把这里的,class,与类的声明关键字,class,混淆在一起,虽然它们由相同的字母组成,但含义是不同的。这里的,class,表示,T,是一个类型参数,可以是任何数据类型,如,int,、,float,、,char,等,或者用户定义的,struct,、,enum,或,class,等自定义数据类型。,为了区别类与模板参数中的类型关键字,class,,标准,C+,提出,了用,typename,作为模板参
10、数的类型关键字,同时也支持使用,class,。比如,把,min,定义的,template,写成下面的形式是完全等价的:,template,T,min(T,a,T,b),7.2.2,函数,模板的实例化,1,、实例化发生的时机,模板实例化发生在调用模板函数时。当编译器遇到程序中对函数模板的调用时,它才会根据调用语句中实参的具体类型,确定模板参数的数据类型,并用此类型替换函数模板中的模板参数,生成能够处理该类型的函数代码,即模板函数。,7.2.2,函数,模板的实例化,7.2.2,函数,模板的实例化,2,、当多次发生类型相同的参数调用时,只在第,1,次进行实例化。假设在例,7-1,中有下面的函数调用:
11、int,x=min(2,3);,int,y=min(3,9);,int,z=min(8.5);,编译器只在第,1,次调用时生成模板函数,当之后遇到相同类型的参数调用时,不再生成其他模板函数,它将调用第,1,次实例化生成的模板函数。,3,、实例化的方式,隐式实例化,编译器能够判断模板参数类型时,自动实例化函数模板为模板函数,template T max(T,T);,int,i=max(1,2);,float f=max(1.0,2.0);,char,ch,=max(a,A);,隐式实例化,表面上是在调用模板,实际上是调用其实例,7.2.2,函数模板,的实例化,显示实例化,explicit in
12、stantiation,时机,编译器不能判断模板参数类型或常量值,需要使用特定数据类型实例化,语法形式,模板名称,(,参数,),示例,1,template T max(T,T);,int,i=max(1,2);,/error:data type cant be deduced,int,i=max(1,2);,7.2.2,函数,模板的实例化,7.2.3,模板参数,1,、模板参数的转换问题,C+,在实例化函数模板的过程中,只是简单地将模板参数替换成调用实参的类型,并以此生成模板函数,不会进行参数类型的任何转换。,7.2.2,函数,模板的实例化,【,例,7-2】,求两个数最大值的普通函数。,/Eg7
13、2.cpp,#include,using namespace std;,double,max(double,a,double,b)return,(a,b)?a:b,;,void main(),double a=2,b=3.4;,float c=5.1,d=3.2;,cout,2,3.2,的最大值是:,max(2,3.2),endl,;,cout,a,c,的最大值是:,max(a,c,),endl,;,cout,a,3,的最大值是:,max(a,3),endl,;,7.2.2,函数,模板的实例化,【,例,7-2】,求两个数最大值的普通函数。,/Eg7-2.cpp,#include,using
14、namespace std;,double,max(double,a,double,b)return,(a,b)?a:b,;,void main(),double a=2,b=3.4;,float c=5.1,d=3.2;,cout,2,3.2,的最大值是:,max(2,3.2),endl,;,cout,a,c,的最大值是:,max(a,c,),endl,;,cout,a,3,的最大值是:,max(a,3),endl,;,7.2.2,函数,模板的实例化,【,例,7-3】,求最大值的函数模板。,/Eg7-3.cpp,#include,using namespace std;,template,T
15、max(T,a,T,b),return(a,b)?a:b,;,void main(),double a=2,b=3.4;,float c=5.1,d=3.2;,cout,2,3.2,的最大值是:,max(2,3.2),endl,;,cout,a c,的最大值是:,max(a,c,),endl,;,cout,a,3,的最大值是:,max(a,3),endl,;,7.2.2,函数,模板的实例化,编译例,7-3,程序,将会产生,3,个编译错误:,error C2782:T_cdecl,max(T,T):template,parameter T is ambiguous could be doubl
16、e or,int,error C2782:T_cdecl,max(T,T):template,parameter T is ambiguous could be float or double,error C2782:T_cdecl,max(T,T):template,parameter T is ambiguous could be,int,or char,产生这个错误的原因是模板实例化过程中不会进行任何形式的参数类型转换,但在普通函数的调用过程中,,C+,会对类型不匹配的参数进行隐式的类型转换。从而导到模板函数的参数类型不匹配,因此产生上述编译错误,7.2.2,函数,模板的实例化,模板参数
17、转换的方法,(,1,)在模板调用时进行参数类型的强制转换,cout,max(,double(2,),3.2),endl,;,(,2,)显式指定函数模板实例化的类型参数,cout,max(,2,3.2),endl,;,cout,max(a,3,),endl,;,(,3,)指定多个模板参数,【,例,7-4】,用两个模板参数实现求最大值的函数。,/Eg7-4.cpp,#include,using namespace std;,template,T1 max(T1 a,T2 b),return(a,b)?a:b,;,void main(),double a=2,b=3.4;,float c=5.1,d
18、3.2;,cout,2,3.2,的最大值是:,max(2,3.2),endl,;,cout,a,c,的最大值是:,max(a,c,),endl,;,cout,a,3,的最大值是:,max(a,3),endl,;,7.2.2,函数,模板的实例化,2.,模板函数的形参表,函数模板参数可以是类属参数,也可以包括普通类型的参数。,【,例,7-5】,用函数模板实现数组的选择法排序,,/Eg7-5.cpp,#include,using namespace std;,template,void,sort(T,&,a,int,n),for(,int,i=0;i,n;i,+),int,p=i;,for(int
19、j=,i;j,n;j,+),if(ap,aj,),p=j;,int,t=,ai,;,ai,=,ap,;,ap,=t;,template,void,display(T,&,a,int,n),for(int,i=0;i,n;i,+),cout,ai,t;,cout,b?a:b;,这肯定是有问题的,因为字符串的比较为:,char*max(char*a,char*b)return,strcmp(a,b)0?a:b;,7.2.4,函数,模板的特化,2,、特化,所谓特化,就是针对模板不能处理的特殊数据类型,编写与模板同名的特殊函数专门处理这些数据类型。,模板特化的定义形式:,template,返回类型
20、函数名,(,参数表,),说明:,template,是模板特化的关键字,,中不需要任何内容;函数名后的,中是需要特化处理的数据类型。,【,例,7-6】,求两数最大值的函数模板,并且特化对字符串数据的最大值计算。,/Eg7-6.cpp,#include,using namespace std;,template,T,max(T,a,T,b),return(a,b)?a:b,;,template /,特化,char*max(char*,a,char,*b),return(,strcmp(a,b,)=0)?a:b;,void main(),float c=5.1,d=3.2;,cout,2,,,3.2
21、的最大值是:,max(3,2),endl,;,cout,a,,,c,的最大值是:,max(c,d,),endl,;,cout,max(xbv,xyce,),endl,;,7.2.4,函数,模板的特化,3,、说明,当程序中同时存在模板和它的特化时,特化将被优先调用;,在同一个程序中,除了函数模板和它的特化外,还可以有同名的普通函数。其区别在于,C+,会对普通函数的调用实参进行隐式的类型转换,但不会对模板函数及特化函数的参数进行任何形式的类型转换。,当同一程序中具有模板与普通函数时,其匹配顺序如下:,完全匹配的非模板函数,完全匹配的模板函数,类型相容的非模板函数,7.2.4,函数,模板的特化,7
22、3,类模板,7.3.1,类模板的概念,类模板可用来设计结构和成员函数完全相同,但所处理的数据类型不同的通用类。,如栈,存在,双精度栈:,class,doubleStack,private:,double,datasize,;,;,字符栈:,class,charStack,private:,char,datasize,;,;,这些栈除了数据类型之外,操作完全相同,就可用类模板实现。,1,、类模板的声明,template,class,类名,/,类成员的声明与定义,其中,T1,、,T2,是类型参数,类模板中可以有多个模板参数,包括类型参数和非类型参数,7.3.2,类,模板的定义,7.3.2,类,模
23、板的定义,非类型参数是指某种具体的数据类型,在调用模板时只能为其提供用相应类型的常数值。非类型参数是受限制的,通常可以是整型、枚举型、对象或函数的引用,以及对象、函数或类成员的指针,但不允许用浮点型(或双精度型)、类对象或,void,作为非类型参数。,在下面的模板参数表中,,T1,、,T2,是类型参数,,T3,是非类型参数。,template,在实例化时,必须为,T1,、,T2,提供一种数据类型,为,T3,指定一个整常数(如,10,),该模板才能被正确地实例化。,2,、类模板的成员函数的定义,方法,1,:在类模板外定义,语法,template,返回值类型 类模板名,:,成员函数名,(,参数列表
24、);,方法,2,:成员函数定义,与常规成员函数的定义类似,另外,“模板参数列表”引入的“类型标识符”作为数据类型使用,“模板参数列表”引入的“普通数据类型常量”作为常量使用,7.3.2,类,模板的定义,【,例,7-7】,设计一个堆栈的类模板,Stack,,在模板中用类型参数,T,表示栈中存放的数据,用非类型参数,MAXSIZE,代表栈的大小,。,/Eg7-7.cpp,/,Stack.h,template,class Stack,private:,T,elemsMAXSIZE,;,int,top;,public:,Stack()top,=0;,void,push(T,e);,T pop();,
25、bool,empty()return,top=0;,bool,full()return,top=MAXSIZE;,;,template,void Stack:,push(T,e),if(top,=MAXSIZE),cout,栈已满,不能再加入元素了!,;,return;,elemstop,+=e;,template,inline T Stack:pop(),if(top,=0),cout,栈已空,不能再弹出元素了!,endl,;,return 0;,top-;,return,elemstop,;,7.3.3,类,模板实例化,1,、类模板实例化的内容,包括,模板实例化,和,成员函数实例化,2,、
26、类模板实例化的时间,当用,类模板定义对象,时,引起类模板的实例化,3,、实例化的方法:,在实例化类模板时,如果模板参数是类型参数,则必须为它指定具体的类型;如果模板参数是非类型参数,则必须为它指定一个常量值。,4,、例如,如对,Stack,类模板,下面的定义将引起实例化,Stack,iStack,;,编译器实例化,Stack,的方法是:将,Stack,模板声明中的所有类型参数,T,替换成,int,,将所有的非类型参数,MAXSIZE,替换成,10,,生成了一个,int,类型的模板类。,class Stack,private:,int,elems10;,int,top;/,栈顶指针,public
27、Stack()top,=0;,void,push(int,e);/,入栈操作,int,pop();/,出栈操作,bool,empty()return,top=0;,bool,full();,;,Stack,模板能够实例化出无穷多的模板类,7.3.4,类,模板的使用,为了使用类模板对象,必须显式地指定模板实参。,/Eg7-7b.cpp,#,includestack.h,/,该头文件的内容见例,7-7,所示的程序清单,#include,using,std:cout,;/,只使用,std,域名空间中的,cout,using,std:endl,;/,只使用,std,域名空间中的,endl,void
28、 main(),Stack,iStack,;,Stack,cStack,;,cout,-,intStack-n,;,int,i;,for(i,=1;i10;i+),iStack.push(i,);,for(i,=1;i10;i+),cout,iStack.pop,()t;,cout,nn-charStack-n,;,cStack.push(A,);,cStack.push(B,);,cStack.push(C,);,cStack.push(D,);,cStack.push(E,);,for(i,=1;i6;i+),cout,cStack.pop,()t;,cout,endl,;,7.3.4,类
29、模板的使用,【,例,7-8】,对例,7-6,建立的,Stack,类模板编写一个函数,display,,该函数能够读取并显示,Stack,模板类建立的栈中的所有元素。,/Eg7-8.cpp,#,includestack.h,#include,using namespace std;,template,void,display(Stack,&s),while(!,s.empty,(),cout,s.pop,()t;,cout,endl,;,void main(),Stack,iStack,;,cout,-,intStack-n,;,for(int,i=1;i10;i+),iStack.push(
30、i,);,display(iStack,);,7.3.5,类模板特化,1,、由类模板生成的模板类都能够正常地工作,但也有由类模板生成的模板类代码对某些数据类型不适用的情况。,【,例,7-9】,设计一通用数组类,它能够直接存取数组元素,并能够对数组进行从大到小的排序。,7.3.5,类模板特化,/Eg7-9.cpp,#include,#include,using namespace std;,const,int,Size=5;,template,class Array,private:,T,aSize,;,public:,Array(),for(int,i=0;i,Size;i,+),ai,=0;
31、T&,operator(int,i);,void Sort();,template T&Array:,operator(int,i),if(i,Size-1),cout,n,数组下标越界!,n;,exit(1);,return,ai,;,template void Array:Sort(),for(int,i=0;iSize-1;i+),int,p=i;,for(int,j=i+1;j,Size;j,+),if(ap,aj,)p=j;,T t=,ap,;,ap,=,ai,;,ai,=t;,void main(),Array a1;,Arrayb1;,a10=1;a11=23;a12=6;,a1
32、3=3;a14=9;,a1.Sort();,for(int,i=0;i5;i+),cout,a1it;,cout,endl,;,b10=x1;b11=,ya,;b12=ad;,b13=be;b14=,bc,;,b1.Sort();,for(i,=0;i5;i+),cout,b1it;,cout,endl,;,程序运行结果如下:,这个结果是错误的!,239631,x1,ya,adbe,bc,7.3.5,类模板特化,2,、特化,解决例,7-9,的方法是特化。即用与该模板相同的名字为某种数据类型专门重写一个模板类。,类模板有两种特化方式:一种是特化整个类模板,另一种是特化个别成员函数,特化成员函数的
33、方法:,template,返回类型 类模板名,:,特化成员函数名,(,参数表,),/,函数定义体,特化例,7-9,的,sort,成员函数,template void Array:Sort(),for(int,i=0;iSize-1;i+),int,p=i;,for(int,j=i+1;j,Size;j,+),if(strcmp(ap,aj,)0),p=j;,char*t=,ap,;,ap,=,ai,;,ai,=t;,7.3.5,类模板特化,为某种数据类型特化整个类模板也要以,template,开头,形式如下:,template class,类模板名,/,类成员定义,7.4 STL,STL,就是
34、标准模板库(,Standard Template Library,),是,C+,较晚加入的基于模板技术的一个库,它提供了模板化的通用类和通用函数。,STL,的核心内容包括容器、迭代器、算法三部分,,三者常常协同工作,为各种编程问题提供有效的解决方案。,7.4.1,容器,1,、,C+,容器的概念及类型,容器(,container,)是用来存储其他对象的对象,它是用模板技术实现的。,STL,的容器常被分为顺序容器、关联容器和容器适配器三类。,C+,提供的顺序类型容器有向量(,vector,)、链表(,list,)、双端队列(,deque,)。,关联容器主要包括集合(,set,)、多重集合(,mul
35、tiset,),容器适配器主要指堆栈(,stack,)和队列(,queue,),表,7-1 STL,中的容器及头文件名,容器名,头文件名,说,明,Vector,向量,从后面快速插入和删除,直接访问任何元素,List,双向链表,Deque,双端队列,Set,元素不重复的集合,multiset,元素可重复的集合,Stack,堆栈,后进先出(,LIFO,),Map,一个键只对于一个值的映射,multimap,一个键可对于多个值的映射,queue,队列,先进先出(,FIFO,),priority_queue,优先级队列,表,7-2,所有容器都具有的成员函数,成员函数名,说,明,默认构造函数,对容器进行
36、默认初始化的构造函数,常有多个,用于提供不同的容器初始化方法,拷贝构造函数,用于将容器初始化为同类型的现有容器的副本,析构函数,执行容器销毁时的清理工作,empty(),判断容器是否为空,若为空返回,true,,否则返回,false,max_size,(),返回容器最大容量,即容器能够保存的最多元素个数,size,返回容器中当前元素的个数,operator=,将一个容器赋给另一个同类容器,operator,如果第,1,个容器小于第,2,个容器,则返回,true,,否则返回,false,operator,如果第,1,个容器大于第,2,个容器,则返回,true,,否则返回,false,operat
37、or=,如果第,1,个容器大于等于第,2,个容器,则返回,true,,否则返回,false,swap,交换两个容器中的元素,表,7-3,顺序和关联容器共同支持的成员函数,成员函数名,说,明,begin(),指向第一个元素,end(),指向最后一个元素,rbegin,(),指向按反顺序的第一个元素,rend(),指向按反顺序的末端位置,erase(),删除容器中的一个或多个元素,clear(),删除容器中的所有元素,7.4.1,容器,1,Vector,vector,是向量容器,它具有存储管理的功能,在插入或删除数据时,,vector,能够自动扩展和压缩其大小。可以像数组一样使用,vector,,
38、通过运算符,访问其元素,但它比数组更灵活,当添加数据时,,vector,的大小能够自动增加以容纳新的元素。图是向量的一个示意图。,【,例,7-10】vector,向量的应用举例。,/Eg7-10.cpp,#include,#include /,向量头文件,using namespace std;,void,display(vector,&v),while(!v.empty,(),cout,v.back,()t;/,输出向量的尾部元素,v.pop_back,();/,删除向量尾部元素,cout,endl,;,void main(),int,a=1,2,3,4,5,6;,vector v1,v2;
39、/,定义只有,0,个元素的向量,v1,、,v2,vector v3(a,a+6);/,定义向量,v3,,并用,a,数组初始化该向量,vector v4(6);/,定义具有,6,个元素的向量,v4,v1.push_back(10);/,在,v1,向量的尾部加入元素,10,v1.push_back(11);,v1.push_back(12);,v1.insert(v1.begin(),30);/,将,30,插入到,v1,向量的最前面,v2=v1;/,将,v1,赋值给,v2,,,v2,与,v1,具有相同的元素,v3.assign(3,10);/,将,v3,的前,3,个元素都设置为,10,cout,v
40、1:;display(v1);,cout,v2:;display(v2);,cout,v3:;display(v3);,v40=10;v41=20;/,用数组方式访问向量元素,v42=30;v43=40;,cout,v4:;,for(int,i=0;i6;i+),cout,v4it;,cout,endl,;,v4.resize(10);/,重置向量,v4,的大小,已有元素不受影响,cout,v4:;display(v4);,7.4.1,容器,2,List,STL,中的,list,是一个双向链表,可以从头到尾或从尾到头访问链表中的节点,节点可以是任意数据类型。链表中节点的访问常常通过迭代器进行。
41、下图是一个链表的示意图。,7.4.1,容器,【,例,7-11】list,应用的一个例子。,/Eg7-11.cpp,#include,#include /,链表头文件,using namespace std;,void main(),int,i;,list L1,L2;,int,a1=100,90,80,70,60;,int,a2=30,40,50,60,60,60,80;,for(i,=0;i5;i+),L1.push_back(a1i);/,将,a1,数组加入到,L1,链表中,for(i,=0;i7;i+),L2.push_back(a2i);/,将,a2,数组加入到,L2,链表中,L1.r
42、everse();/,将,L1,链表倒序,L1.merge(L2);/,将,L2,合并到,L1,链表中,cout,L1,的元素个数为:,L1.size(),endl,;,L1.unique();/,删除,L1,中相邻位置的相同元素,只留,1,个,while(!L1.empty(),cout,L1.front()t;,L1.pop_front();/,删除,L1,的链首元素,cout,endl,;,;,7.4.1,容器,3,Stack,堆栈(,stack,)是一种较简单的常用容器,它是一种受限制的向量,只允许在向量的一端存取元素,后进栈的元素先出栈,即,LIFO,(,last in first
43、out,)。右图是一个字符堆栈的示意图。,【,例,7-12】STL stack,应用的例子。,/Eg7-12.cpp,#include,#include,using namespace std;,void main(),stack s;,s.push(10);s.push(20);s.push(30);,cout,s.top,()t;,s.pop,();,s.top,()=100;,s.push(50);s.push(60);,s.pop,();,while(!s.empty,(),cout,s.top,()t;,s.pop,();,cout,s1s2,若,s1,大于,s2,,结果为真,否则为
44、假,=,s1=s2,若,s1,等于,s2,,结果为真,否则为假,=,s1=s2,若,s1,大于或等于,s2,,结果为真,否则为假,s1s2,若,s1,小于,s2,,结果为真,否则为假,=,s1=s2,若,s1,小于或等于,s2,,结果为真,否则为假,!=,s1!=s2,若,s1,不等于,s2,,结果为真,否则为假,+=,s1+=s2,将,s2,连接在,s1,后面,并赋值给,s1,s1=a,string,可用数组方式访问元素,起始下标为,0,7.4.1,容器,【,例,7-13】string,应用的例子。,/Eg7-13.cpp,#include,#include,using namespace
45、std;,void main(),string s1=,中华人民共和国成立了,;,string s2=,中国人民从此站起来了!,;,string s3,s4,s5;,s3=s1+,,,+s2;,int,n=s1.find_first_of(,人民,);,if(n!=,string:npos,),cout,人民在,s1,中的位置:,n,endl,;,else,cout,在,s1,中没有该子串!,;,s4=s1.substr(4,10);,cout,s1=s1,endl,;,cout,s2=s2,endl,;,cout,s3=s3,endl,;,cout,s4=s4s2),cout,s2=true
46、endl,;,else,cout,s2=false,endl,;,s3.replace(s3.find(,从此,),4,从,1949,年,);,cout,s3 after replace=s3,endl,;,s3.insert(s3.find(,站,),10,月,);,cout,s3 after insert=s3,endl,;,7.4.2,迭代器,1,、迭代器的概念,迭代器(,iterator,)是一个对象,常用它来遍历容器,即在容器中实现“取得下一个元素”的操作。,迭代器的操作类似于指针,但它是基于模板的“功能更强大、更智能、更安全的指针”,用于指示容器中的元素位置,通过迭代器能够遍历容
47、器中的每个元素。,7.4.2,迭代器,2,、迭代器的操作,迭代器提供的基本操作包括:,在容器中的特定位置定位迭代器。,在迭代器指示位置检查是否存在对象。,获取存储在迭代器指示位置的对象值。,改变迭代器指示位置的对象值。,在迭代器指示位置插入新对象。,将迭代器移到容器中的下一个位置。,7.4.2,迭代器,3,、迭代器提供的主要操作如下:,operator*,返回当前位置上的元素值,operator+,将迭代器前进到下一个元素位置,operator-,将迭代器后退到前一个元素位置,operator=,或,operator!=,operator=,为迭代器赋值,begin(),指向容器起点(即第一个
48、元素)位置,end(),指向容器的结束点,rbegin,(),指向按反向顺序的第一个元素位置,rend(),指向按反向顺序的最后一个元素后的位置,7.4.2,迭代器,【,例,7-14】,链表迭代器应用举例。,/Eg7-14.cpp,#include,#include,using namespace std;,int,main(),int,i;,list L1,L2,L3(10);,list:,iterator,iter,;/,定义迭代器,iter,int,a1=100,90,80,70,60;,int,a2=30,40,50,60,60,60,80;,for(i,=0;i5;i+),L1.pu
49、sh_back(a1i);,for(i,=0;i7;i+),L2.push_front(a2i);,for(iter,=L1.begin();iter!=L1.end();iter+),cout,*,iter,t,cout,endl,;,int,sum=0;,/,通过迭代器反向输出,L2,的所有元素,for(iter,=-L2.end();iter!=L2.begin();iter-),cout,*,iter,t;,sum+=*,iter,;/,计算,L2,所有链表节点的总和,cout,nL2:sum=sum,endl,;,int,data=0;,/,通过迭代器修改,L3,链表的内容,for(
50、iter,=L3.begin();iter!=L3.end();iter+),*,iter,=data+=10;,for(iter,=L3.begin();iter!=L3.end();iter+),cout,*,iter,t;,cout,endl,;,return 0;,7.4.3,关联,式容器,STL,关联式容器包括集合和映射两大类,集合包括,set,和,multiset,,映射包括,map,和,multimap,,它们通过关键字(也称查找关键字)存储和查找元素。在每种关联容器中,关键字按顺序排列,容器遍历就以此顺序进行。,7.4.3,关联,式容器,1,set,和,multiset,mul






