pc端微信端网站建设,磐安县住和城乡建设局网站,小程序开发网上商城,捕鱼游戏网站制作模板C提高编程1.模板1.1模板的概念1.2函数模板1.2.1函数模板语法1.2.2函数模板注意事项1.2.3函数模板案例1.2.4普通函数与函数模板的区别1.2.5普通函数与函数模板的调用规则1.2.6模板的局限性1.3类模板1.3.1类模板语法1.3.2类模板和函数模板区别1.3.3类模板中成员函数创建时机1.3.4…
C提高编程1.模板1.1模板的概念1.2函数模板1.2.1函数模板语法1.2.2函数模板注意事项1.2.3函数模板案例1.2.4普通函数与函数模板的区别1.2.5普通函数与函数模板的调用规则1.2.6模板的局限性1.3类模板1.3.1类模板语法1.3.2类模板和函数模板区别1.3.3类模板中成员函数创建时机1.3.4类模板对象做函数参数1.3.5类模板与继承1.3.6类模板成员函数类外实现1.3.7类模板分文件编写1.3.8类模板与友元1.3.9类模板案例2.STL初始2.1STL的诞生2.2STL的基本概念2.3STL六大组件2.4STL容器、算法、迭代器2.4.1容器2.4.2算法2.4.3迭代器2.5容器算法迭代器初识2.5.1 vector存放内置数据类型2.5.2vector存放自定义数据类型2.5.3容器嵌套3.STL-常用容器3.1string容器3.1.1string基本概念3.1.2string构造函数3.1.3string赋值操作3.1.4string字符拼接3.1.5string查找和替换3.1.6string字符串比较3.1.7string字符存取3.1.8string插入和删除3.1.9string子串3.2vector容器3.2.1vector基本概念1.功能2.vector与普通数组区别3.动态扩展3.2.2vector构造函数3.2.3vector赋值操作3.2.4vector容量和大小3.2.5vector插入和删除3.2.6vector数据存取3.2.7vector互换容器3.2.8vector预留空间3.3deque容器3.3.1deque容器基本概念3.3.2deque构造函数3.3.3deque赋值操作3.3.4deque大小操作3.3.5deque插入删除3.3.6deque数据存取3.3.7deque排序3.4案例3.5stack容器3.5.1stack基本概念3.5.3stack常用接口1.构造函数2.赋值操作3.数据存取4.大小操作3.6queue容器3.6.1queue基本概念3.6.2queue常用接口1.构造函数2.赋值操作3.数据存取4.大小操作3.7list容器3.7.1list基本概念3.7.2list构造函数3.7.3list赋值和交换3.7.4list大小操作3.7.5list插入和删除3.7.6list数据存取3.7.7list反转和排序3.8set/multiset容器3.8.1set基本概念1.简介2.本质3.set和multiset区别3.8.2set构造和赋值3.8.3set大小和交换3.8.4set插入和删除3.8.5set查找和统计3.8.6set和multiset区别3.8.7pair对组创建3.8.8set容器排序3.9map/multimap容器3.9.1map基本概念1.简介2.本质3.优点4.map和multimap区别3.9.2map构造和赋值3.9.3map大小和交换3.9.4插入和删除3.9.5map查找和统计3.9.6map容器排序1.模板 
1.1模板的概念 
模板就是建立通用的摸具大大提高复用性模板的特点 模板不可以直接使用它只是一个框架模板的通用并不是万能的  
1.2函数模板 
C中另一种编程思想称为泛型编程主要利用的技术就是模板C提供两种模板机制:函数模板和类模板 
1.2.1函数模板语法 函数模板作用 建立一个通用函数其函数返回值类型和形参类型可以不具体定制用一个虚拟的类型来代表  语法  
templatetypename T
函数声明或定义解释 template — 声明创建模板typename — 表面起后面的符号是一种数据类型可以用class替代T — 通用的数据类型加粗样式名称可以替换通常为大写字母  
#includeiostream
using namespace std;//函数模板
templatetypename T //声明一个模板告诉编译器后面代码紧跟的T不要报错T是一个通用类型
void mySwap(T a, T b) 
{T temp  a;a  b;b  temp;
}void test1()
{// 两种方式使用函数模板// 1.自动类型推导int a  20;int b  40;mySwap(a, b);cout  a    a  endl; // 40cout  b    b  endl; // 20// 2.显示指定类型mySwapint(a, b);cout  a    a  endl; // 20cout  b    b  endl; // 40
}int main() 
{test1();system(pause);return 0;
}1.2.2函数模板注意事项 
注意事项 自动类型推导必须推导出一致的数据类型T才可以使用模板必须要确定出T的数据类型才可以使用  
#includeiostream
using namespace std;templatetypename T
void mySwap(T a,T b)
{T temp  a;a  b;b  temp;
}//模板必须要确定出T的数据类型才可以使用
templatetypename T
void func()
{cout  func的调用  endl;
}void test1() {int a  10;int b  30;char c  a;mySwap(a, b);// mySwap(a, c); // error,推导不出不一致的T类型cout  a    a  endl;cout  b    b  endl;
}
void test2() 
{funcint();
}int main()
{//test1();test2();system(pause);return 0;
}1.2.3函数模板案例 
#includeiostream
using namespace std;templatetypename T
void mySwap(T a,T b)
{T temp  a;a  b;b  temp;
}
templatetypename T
void arrSort(T arr[],int len)
{for (int i  0;i  len;i) {int max  i;for (int j  i  1;j  len;j) {if (arr[max]  arr[j]) {max  j;}}if(max ! i){mySwap(arr[max], arr[i]);}}
}
templatetypename T
void showArr(T arr[], int len)
{for (int i  0;i  len;i) {cout  arr[i]   ;}cout  endl;
}
void test1() 
{char arr[]  abefcej;arrSortchar(arr, sizeof(arr) / sizeof(char));showArr(arr, sizeof(arr) / sizeof(char));
}
int main()
{test1();system(pause);return 0;
}1.2.4普通函数与函数模板的区别 
区别 普通函数调用时可以发生自动类型转换(隐式类型转换)函数模板调用时如果利用自动类型推导不会发生隐式类型转换如果利用显示指定类型的方式可以发生隐式类型转换  
#includeiostream
using namespace std;//函数模板
templatetypename T
T myAdd2(T a, T b)
{return a  b;
}// 普通函数
int myAdd(int a, int b) {return a  b;
}
void test1() {int a  12;int b  13;char c  s;cout  myAdd(a, b)  endl;// 25// 隐藏类型转化cout  myAdd(a, c)  endl;// 127cout  myAdd2(a, b)  endl;// 25// 自动类型推导  -- 不能自动转换(隐式转换)//cout  myAdd2(a, c)  endl;// error//显示指定类型cout  myAdd2int(a, c)  endl;// 127
}int main() {test1();system(pause);return 0;
}总结: 建议使用显示指定类型的方式调用函数模板自己可以确定通用类型 
1.2.5普通函数与函数模板的调用规则 
调用规则 如果函数模板和普通函数都可以实现优先调用普通函数可以通过空模板参数列表来强制调用函数模板函数模板也可以发生重载如果函数模板可以产生更好的匹配优先调用函数模板  
#includeiostream
using namespace std;void myPrint(int a,int b)
{cout  调用普通函数  endl;
}template typename T
void myPrint(T a, T b)
{cout  调用函数模板  endl;
}template typename T
void myPrint(T a, T b,T c)
{cout  调用函数模板的重载  endl;
}void test1()
{int a  10;int b  20;//函数模板和普通函数都可以调用优先调用普通函数//普通函数只有函数声明调用会报错myPrint(a, b);//空模板参数列表强制调用函数模板myPrint(a, b);//函数模板可以发生重载myPrint(a, b, 20);//函数模板产生更好的匹配优先调用函数模板char a1  a;char b1  b;myPrint(a1, b1);// 调用函数模板
}int main() 
{test1();system(pause);return 0;
}1.2.6模板的局限性 
局限性 模板的通用性并不是万能的 利用具体化的模板可以解决自定义类型的通用化 
#includeiostream
using namespace std;
#includestring
class Person
{
public:Person(string name,int age){this-m_Name  name;this-m_Age  age;}string m_Name;int m_Age;
};templatetypename T
bool myCompare(T a, T b)
{if (a  b) {return true;}else {return false;}
}
// 利用具体化Person的版本实现代码具体优先调用
template bool myCompare(Person p1, Person p2)
{if (p1.m_Name  p2.m_Name  p1.m_Age  p2.m_Age) {return true;}else {return false;}
}void test1()
{int a  10;int b  20;bool res  myCompare(a, b);if (res) {cout  ab  endl;}else {cout  a ! b  endl;}
}
void test2()
{Person person1(Jack, 20);Person person2(Jack, 20);bool res  myCompare(person1, person2);if (res) {cout  person1  person2  endl;}else {cout  person1 ! person2  endl;}
}
int main()
{//test1();test2();system(pause);return 0;
}1.3类模板 
1.3.1类模板语法 类模板的作用 建立一个通用类类中的成员 数据类型 可以不具体规定用一个虚拟的类型来代表  语法 templateclass T 
类template — 声明创建模板class — 表明其后免得符号是一种数据类型可以用 typename 代替T — 通用的数据类型名称可以替换通常为大写字幕  
#includeiostream
using namespace std;
#includestring//类模板
templateclass NameType,class AgeType
class Person 
{
public:Person(NameType name,AgeType age) {this-m_Name  name;this-m_Age  age;}void showPerson() {cout  name  this-m_Name  ,age  this-m_Age  endl;}NameType m_Name;AgeType m_Age;};
void test1() 
{Personstring, int p1(类模板, 20);p1.showPerson();
}int main()
{test1();system(pause);return 0;
}1.3.2类模板和函数模板区别 
类模板和函数模板的区别 类模板没有自动类型推导的使用方式类模板在模板参数列表中可以有默认参数  
#includeiostream
using namespace std;//类模板和函数模板的区别//类模板在参数列表中可以有默认参数    AgeType  int
templateclass NameType,class AgeType  int
class Person
{
public:Person(NameType name,AgeType age){this-m_Name  name;this-m_Age  age;}void showPerson(){cout  name  this-m_Name  ,age  this-m_Age  endl;}NameType m_Name;AgeType m_Age;
};void test1()
{// 类模板没有自动化类型推导使用方式//Person p(数字化, 10);Personstring, int p(数字化, 10);p.showPerson();
}
void test2()
{Personstring p(智能化, 10);p.showPerson();
}
int main()
{//test1();test2();system(pause);return 0;
}1.3.3类模板中成员函数创建时机 
类模板中成员函数和普通类中成员函数创建时机是有区别的 普通类中成员函数一开始就可以创建类模板中成员函数在调用时才创建  
#includeiostream
using namespace std;class Person1
{
public:void showPerson1(){cout  Person1 show  endl;}
};class Person2
{
public:void showPerson2(){cout  Person2 show  endl;}
};templateclass T
class MyClass
{
public:T obj;//类模板的成员函数void fun1() {obj.showPerson1();}void fun2() {obj.showPerson2();}
};void test1() {MyClassPerson1 m;m.fun1();// 类模板中成员函数在调用时创建// m.fun2();
}
int main() {system(pause);return 0;
}1.3.4类模板对象做函数参数 
类模板实例化出的对象向函数传参的方式 指定传入的类型 — 直接显示对象的数据类型 推荐参数模板化 — 将对象中的参数变为模板进行传递整个类模板化 — 将这个对象类型 模板化 进行传递  
#includeiostream
using namespace std;
templateclass T,class K
class Person
{
public:Person(T name, K age) {this-m_Name  name;this-m_Age  age;}void showPerson() {cout  name  this-m_Name  ,age  this-m_Age  endl;}T m_Name;K m_Age;};
// 1.指定传入类型推荐
void printPerson1(Personstring, int p)
{p.showPerson();
}void test1() {Personstring, int p(智能化, 120);printPerson1(p);
}// 2.参数模板化
templateclass T,class K
void printPerson2(PersonT, K p) {p.showPerson();//查看推导的类型cout  T的类型为:  typeid(T).name()  endl; //class std::basic_stringchar,struct std::char_traitschar,class std::allocatorchar cout  K的类型为:  typeid(K).name()  endl; //int
}void test2() {Personstring, int p(数字化, 10);printPerson2(p);
}// 3.整个类模板化
templateclass T
void printPerson3(T p) {p.showPerson();cout  T的数据类型:   typeid(T).name()  endl;
}
void test3() {Personstring, int p(自动化, 30);printPerson3(p);
}int main() {//test1();//test2();test3();system(pause);return 0;
}1.3.5类模板与继承 
类模板碰到继承时需要注意一下几点 当子类继承的父类是一个类模板时子类在声明的时候要指定出父类中的T类型如果不指定编译器无法给子类分配内存如果想灵活指定出父类中的T的类型子类也需要变成类模板  
#includeiostream
using namespace std;
#includestringtemplateclass T,class K
class Person
{
public:Person(T name, K age);/*{this-m_Name  name;this-m_Age  age;}*/void showPerson();/*{cout  姓名:   this-m_Name  年龄  this-m_Age  endl;}*/T m_Name;K m_Age;};//构造函数的类外实现
templateclass T,class K
PersonT,K::Person(T name, K age) 
{this-m_Name  name;this-m_Age  age;
}
// 成员函数的类外实现
templateclass T,class K
void PersonT, K::showPerson() 
{cout  姓名:   this-m_Name  年龄  this-m_Age  endl;
}void test1() 
{Personstring,int p(智能组装, 8);p.showPerson();
}
int main() {test1();system(pause);return 0;
}1.3.6类模板成员函数类外实现 
#includeiostream
using namespace std;
#includestringtemplateclass T,class K
class Person
{
public:Person(T name, K age);/*{this-m_Name  name;this-m_Age  age;}*/void showPerson();/*{cout  姓名:   this-m_Name  年龄  this-m_Age  endl;}*/T m_Name;K m_Age;};//构造函数的类外实现
templateclass T,class K
PersonT,K::Person(T name, K age) 
{this-m_Name  name;this-m_Age  age;
}
// 成员函数的类外实现
templateclass T,class K
void PersonT, K::showPerson() 
{cout  姓名:   this-m_Name  年龄  this-m_Age  endl;
}void test1() 
{Personstring,int p(智能组装, 8);p.showPerson();
}
int main() {test1();system(pause);return 0;
}1.3.7类模板分文件编写 类模板中成员函数创建时机是在调用阶段导致分文件编写时链接不到  解决方式: 直接包含.cpp源文件 头文件 person.h  #pragma once
#includeiostream
using namespace std;
#includestring
templateclass T,class K
class Person
{
public:Person(T name,K age);void showPerson();T m_Name;K m_Age;};源文件 person.cpp  #include person.htemplateclass T, class K
PersonT, K::Person(T name, K age)
{this-m_Name  name;this-m_Age  age;
}templateclass T, class K
void PersonT, K::showPerson()
{cout  姓名:   this-m_Name  年龄  this-m_Age  endl;
}源文件  #includeiostream
using namespace std;
#includestring// 1.第一种解决方式直接包含 源文件
//#include person.cpp// 2.第二种解决方式将.h和.cpp中的内容写到一起将后缀名改为.hpp文件
#includeperson.hpp//templateclass T,class K
//class Person
//{
//public:
//	Person(T name, K age);
//	void showPerson();
//	T m_Name;
//	K m_Age;
//};
//
//templateclass T,class K
//PersonT, K::Person(T name, K age)
//{
//	this-m_Name  name;
//	this-m_Age  age;
//}
//
//templateclass T,class K
//void PersonT, K::showPerson() 
//{
//	cout  姓名:   this-m_Name  年龄  this-m_Age  endl;
//}void test1() 
{Personstring,int person(数据化, 20);person.showPerson();
}int main()
{test1();system(pause);return 0;
}将声明和实现写在同一个文件中并更改后缀名.hpphpp是约定的名称并不是强制 头文件 person.hpp 		#pragma once
#includeiostream
using namespace std;
#includestring
templateclass T, class K
class Person
{
public:Person(T name, K age);void showPerson();T m_Name;K m_Age;};templateclass T, class K
PersonT, K::Person(T name, K age)
{this-m_Name  name;this-m_Age  age;
}templateclass T, class K
void PersonT, K::showPerson()
{cout  姓名:   this-m_Name  年龄  this-m_Age  endl;
}引入方式同上   
1.3.8类模板与友元 
全局函数类内实现 — 直接在类内声明友元即可全局函数类外实现 — 需要提前让编译器知道全局函数的存在 
#includeiostream
#includestring
using namespace std;// 声明Person类
templateclass T, class K
class Person;//类外实现templateclass T, class K
void printPerson2(PersonT, K p)
{cout  -----------全局函数的类外实现-----------  endl;cout  姓名:   p.m_Name  ,年龄:   p.m_Age  endl;
}//类模板
templateclass T,class K
class Person
{// 全局函数  类内实现friend void printPerson(PersonT, K p){cout  姓名:   p.m_Name  ,年龄:   p.m_Age  endl;}//全局函数 类外实现// 加空模板参数列表// 全局函数 是类外实现需要让编译器提前知道这个函数的存在friend void printPerson2(PersonT, K p);public:Person(T name, K age){this-m_Name  name;this-m_Age  age;}
private:T m_Name;K m_Age;
};// 1.全局函数在类内实现
void test1() 
{Personstring, int p(Rose, 18);printPerson(p);
}// 2.全局函数在类外实现
void test2()
{Personstring, int p(Jack, 20);printPerson2(p);
}
int main()
{//test1();test2();system(pause);return 0;
}1.3.9类模板案例 
#pragma once
#includeiostream
using namespace std;templateclass T
class MyArray
{
public:MyArray(int capacity){this-m_Capacity  capacity;this-m_Size  0;this-pAddress  new T[this-m_Capacity];}//析构函数~MyArray(){if (this-pAddress ! NULL) {delete[] this-pAddress;this-pAddress  NULL;}}//拷贝构造MyArray(const MyArray arr) {this-m_Capacity  arr.m_Capacity;this-m_Size  arr.m_Size;//this-pAddress  arr.pAddress;//深拷贝this-pAddress  new T[arr.m_Capacity];//将arr中的数据都拷贝过来for (int i  0;i  this-m_Size;i){this-pAddress[i]  arr.pAddress[i];}}// operator 防止浅拷贝问题MyArray operator(const MyArray arr){//先判断原来堆区是否有数据如果有先释放if (this-pAddress ! NULL){delete[] this-pAddress;this-pAddress  NULL;this-m_Capacity  0;this-m_Size  0;}//深拷贝this-m_Capacity  arr.m_Capacity;this-m_Size  arr.m_Size;this-pAddress  new T[arr.m_Capacity];for(int i  0;ithis-m_Size;i){this-m_Capacity[i]  arr.m_Capacity[i];}return *this;}//尾插法void Push_Back(const T val){// 判断容量是否有空间if (this-m_Capacity  this-m_Size){return;}this-pAddress[this-m_Size]  val;//更新数组大小this-m_Size;}//尾删法void Pop_Back(){//让用户访问不到最后一个元素即为尾删逻辑删除if (this-m_Size  0){return;}this-m_Size--;}//通过下标方式访问数组的元素T operator[](int index){return this-pAddress[index];}//返回数组的容量int getCapacity(){return this-m_Capacity;}//返回数组的大小int getSize(){return this-m_Size;}//遍历数组void printArray(){for (int i  0;i  this-m_Size;i){cout  this-pAddress[i]   ;}cout  endl;}private:// 指针指向堆区开辟的真实数组T* pAddress;// 数据容量int m_Capacity;//数据大小int m_Size;
}; 
#includeiostream
using namespace std;
#include MArray.hppvoid printArray(MyArrayint arr)
{for (int i  0;i  arr.getSize();i){cout  arr[i]  ;}cout  endl;
}void test1()
{MyArrayint arr(5);for (int i  0;i  5;i) {//利用尾插法插入数据arr.Push_Back(i);}printArray(arr);cout  arr的容量为:   arr.getCapacity()  endl;cout  arr的容量为:   arr.getSize()  endl;MyArrayint arr2(arr);cout  ----arr2的打印输出----  endl;printArray(arr2);arr2.Pop_Back();cout  ----arr2尾删后打印输出----  endl;printArray(arr2);cout  arr2的容量为:   arr.getCapacity()  endl;cout  arr2的容量为:   arr.getSize()  endl;//遍历数组arr2.printArray();}int main()
{test1();system(pause);return 0;}2.STL初始 
2.1STL的诞生 
C的面对对象和泛型编程思想目的就是复用性的提升大多数情况下数据结构和算法都未能有一套标准导致被迫从事大量重复工作为了建立数据结构和算法的一套标准诞生了STL 
2.2STL的基本概念 
STL(Standard Template Library,标准模板库)STL从广义上分为容器(container)、算法(algorithm)、迭代器(iterator)容器和算法之间通过迭代器进行无缝连接STL几乎所有的代码都采用了模板类或模板函数 
2.3STL六大组件 
STL分为六大组件 容器各种数据结构如vector、list、deque、set、map等等用来存放数据算法各种常用的算法如sort、find、copy、for_each等迭代器扮演了容器与算法之间的胶合剂仿函数行为类似函数可作为算法的某种策略适配器一种用来修饰容器或仿函数或迭代器接口的东西空间配置器负责空间的配置与管理  
2.4STL容器、算法、迭代器 
2.4.1容器 
STL容器就是运用最广泛的一些数据结构实现出来常用的数据结构 数组链表树栈队列集合映射表 容器分为序列式容器和关联式容器 序列式容器强调值得排序序列式容器中得每个元素均有固定得位置关联式容器二叉树结构各元素之间没用严格得物理上的顺序关系  
2.4.2算法 
有限的步骤解决逻辑或数学上的问题算法分为: 质变算法和非质变算法 质变算法是指运算过程中会更改区间内的元素内容如拷贝、替换、删除非质变算法是指运算过程中不会更改区间内的元素内容例如查找、计数、遍历、寻找极值等等  
2.4.3迭代器 
容器和算法之间粘合剂提供一种方法使之能够依序寻找某个容器所含的各个元素而又无暴露该容器的内部表示方式每个容器都有自己专属的迭代器迭代器使用非常类似于指针迭代器种类: 
种类功能支持运算输入迭代器对数据的只读访问只读支持、、!输出迭代器对数据的只写访问只写支持向前迭代器读写操作并能向前推进迭代器读写支持、、!双线迭代器读写操作并能向前和向后操作读写支持、--随机访问迭代器读写操作可以以跳跃的方式访问任意数据功能最强的迭代器读写支持、--、[n]、-n、、、、
常用的容器迭代器种类为双向迭代器和随机访问迭代器 
2.5容器算法迭代器初识 
2.5.1 vector存放内置数据类型 
容器 vector算法 for_each迭代器 vectorint::iterator 
#includeiostream
#includevector
#includealgorithm
using namespace std;
// vector容器存放内置数据类型//遍历
void printContainer(int val)
{cout  val  ;
}void test1()
{//创建了一个vector容器vectorint vec;//向容器中插入数据vec.push_back(10);vec.push_back(20);vec.push_back(30);vec.push_back(50);vec.push_back(90);vec.push_back(20);// 通过迭代器访问容器中的数据// 起始迭代器  指向容器中第一个元素vectorint::iterator itBegin  vec.begin();// 结束迭代器  指向容器中最后一个元素的下一个位置vectorint::iterator itEnd  vec.end();//第一种遍历方式cout  while循环遍历  endl;while (itBegin ! itEnd){		cout  *itBegin   ;itBegin;}cout  endl;//第二种遍历方式cout  for循环遍历容器  endl;for (vectorint::iterator it  vec.begin();it ! vec.end();it){		cout  *it  ;}cout  endl;//第三种遍历方式for_each(vec.begin(), vec.end(), printContainer);}int main()
{test1();system(pause);return 0;
}2.5.2vector存放自定义数据类型 
#includeiostream
#includevector
#includealgorithm
using namespace std;// vector容器存放自定义数据类型// 自定义数据类型
class Person
{
public:Person(string name, int age){this-m_Name  name;this-m_Age  age;}string m_Name;int m_Age;
};//遍历
void printInfo(Person person)
{cout  标签:   person.m_Name  ,年限:   person.m_Age  endl;
}void test1()
{vectorPerson vp;Person p1(数字化, 10);Person p2(模块化, 23);Person p3(拟人化, 1);Person p4(智能化, 9);Person p5(树脂化, 24);Person p6(机械化, 11);//向容器添加数据vp.push_back(p1);vp.push_back(p2);vp.push_back(p3);vp.push_back(p4);vp.push_back(p5);vp.push_back(p6);//遍历容器中的数据// while方式遍历cout  -----------while遍历---------  endl;vectorPerson::iterator itBegin  vp.begin();vectorPerson::iterator itEnd  vp.end();while (itBegin ! itEnd){cout  标签:   (*itBegin).m_Name  ,年限:   (*itBegin).m_Age  endl;itBegin;}// for方式遍历cout  --------for遍历-------  endl;for (vectorPerson::iterator itBegin  vp.begin();itBegin ! vp.end();itBegin){cout  标签:   (*itBegin).m_Name  ,年限:   (*itBegin).m_Age  endl;}//for_each方式遍历cout  --------for_each遍历-------  endl;for_each(vp.begin(), vp.end(), printInfo);
}
int main()
{test1();system(pause);return 0;
}2.5.3容器嵌套 
#includeiostream
#includevector
#includealgorithm
using namespace std;
// vector容器存放内置数据类型//遍历
void printContainer(int val)
{cout  val  ;
}void test1()
{//创建了一个vector容器vectorint vec;//向容器中插入数据vec.push_back(10);vec.push_back(20);vec.push_back(30);vec.push_back(50);vec.push_back(90);vec.push_back(20);// 通过迭代器访问容器中的数据// 起始迭代器  指向容器中第一个元素vectorint::iterator itBegin  vec.begin();// 结束迭代器  指向容器中最后一个元素的下一个位置vectorint::iterator itEnd  vec.end();//第一种遍历方式cout  while循环遍历  endl;while (itBegin ! itEnd){		cout  *itBegin   ;itBegin;}cout  endl;//第二种遍历方式cout  for循环遍历容器  endl;for (vectorint::iterator it  vec.begin();it ! vec.end();it){		cout  *it  ;}cout  endl;//第三种遍历方式for_each(vec.begin(), vec.end(), printContainer);}int main()
{test1();system(pause);return 0;
}3.STL-常用容器 
3.1string容器 
3.1.1string基本概念 
本质string是c风格的字符串而string本质上是一个类string和char *区别 char * 是一个指针string是一个类类内部封装了char * 管理这个字符串是一个char *型的容器  
3.1.2string构造函数 
构造函数原型 创建空字符串 string();字符串s初始化 string(const char * s);使用一个字符串初始化另一个字符串 string(const string  str);使用n个字符c初始化 string(int n,char c);#includeiostreamusing namespace std;
//string构造函数void test1()
{//1.默认构造函数string s1;//2.字符串初始化const char* str  hello;string s2(str);cout  s2    s2  endl;//3.一个字符串给另一个字符串初始化string s3(s2);cout  s3    s3  endl;//使用n个字符初始化string s4(4, x);cout  s4    s4  endl;}int main()
{test1();system(pause);return 0;
}3.1.3string赋值操作 
给string字符串进行赋值赋值的函数原型 char*类型字符串 赋值给当前的字符串 string operator(const char *s)把字符串s赋值给当前字符串 string operator(const string s)字符赋值给当前字符串 string operator(char c)把字符串赋值给当前的字符串 string  assign(const char *s)把字符串s的前面n个字符赋给当前字符串 string assign(const char * s,int n)把字符串s赋给当前字符串 string assgin(const string s)用n个字符c赋给当前字符串 string assign(int n,char c)#includeiostream
using namespace std;
#includestring
//string赋值操作void test1()
{string str1;str1  hello;cout  str1    str1  endl;string str2;str2  str1;cout  str2    str2  endl;string str3;str3  a;cout  str3    str3  endl;string str4;str4.assign(hello C);cout  str4    str4  endl;string str5;str5.assign(hello c,5);cout  str5    str5  endl;string str6;str6.assign(str5);cout  str6    str6  endl;string str7;str7.assign(4, g);cout  str7    str7  endl;
}int main()
{test1();system(pause);return 0;
}3.1.4string字符拼接 
实现在字符串末尾拼接字符串函数原型 重载操作符 string operator(const char* str)
string operator(const char c)
string operator(const string str)把字符串s连接到当前字符串结尾 string append(const char *s)把字符串s的前n个字符连接到当前字符串结尾 string append(const char*s,int n)同operator(const string str) string append(const string s)字符串中从pos开始的n个字符连接到字符换末尾 string append(const string s,int pos,int n)str7   bbb;cout  str7    str7  endl;str7.append(hello, 2, 2);cout  str7    str7  endl; // gggg bbbll3.1.5string查找和替换 
查找: 查找指定字符串是否存在替换: 在指定的位置替换字符串函数原型 查找str字符串第一次出现位置从pos开始查找 int find(const string str,int pos  0) const查找s第一次出现位置从pos开始查找 int find(const char* s,int pos  0) const从pos位置查找s的前n个字符第一次位置 int find(const char s,int pos,int n) const查找字符c第一次出现的位置 int find(const char c,int pos  0) const查找str最后一次位置从pos开始查找 int rfind(const string str,int pos  npos) const查找s最后一次出现位置从pos开始查找 int rfind(const char * s,int pos  npos) const从pos查找s的前n个字符最后一次位置 int rfind(const char s,int pos,int n) const查找字符c最后一次出现的位置 int rfind(const char c,int pos  0) const替换从pos开始n个字符为字符串 string replace(int pos,int n,const string str)替换从pos开始的n个字符为字符串s string replace(int pos,int n,const char* s)3.1.6string字符串比较 
字符串之间的比较逐个比较比较方式 字符串比较是按字符的ASCII码进行对比结果  返回 0 返回 1 返回 -1  函数原型 与字符串s比较 int compare(const string s) const与字符串s比较 int compare(const char * s) conststring strs  hello;string strs1  hollw;int comp  strs.compare(strs1);cout  comp    comp  endl;// -13.1.7string字符存取 
string中单个字符存取通过[ ]方式获取字符 
char operator[](int n)通过at方式获取字符 
char at(int n)string strs  hello;
cout  字符:   strs[2]  endl;// l3.1.8string插入和删除 
对string字符串进行插入和删除字符串操作函数原型 插入字符串 string insert(int pos,const char* s)插入字符串 string insert(int pos,const string str)在指定位置插入n个字符c string insert(int pos,int n,char c)删除从pos开始的n个字符 string erase(int pos,int n  npos)string strs  hello;string str12;str12  strs.erase(1, 3);cout  str12    str12  endl;// ho3.1.9string子串 
从字符串中获取想要的子串函数原型 返回pos开始的n个字符组成的字符串 string substr(int pos  0,int n  npos) conststring strs  hello;string stru;stru  strs.substr(1, 3);cout  stru    stru  endl;// ell3.2vector容器 
3.2.1vector基本概念 
1.功能 
vector数据结构和数组非常类似也称为单端数组 
2.vector与普通数组区别 
不同之处在于数组是静态空间而vector可以动态扩展 
3.动态扩展 
并不是在原空间之后续接新空间而是找更大的内存空间然后将原数据拷贝新空间释放原空间 vector容器的迭代器是支持随机访问的迭代器 
3.2.2vector构造函数 
创建vector容器函数原型 采用模板实现类实现默认构造函数 vectorT v;将v[begin(),end()]区间中的元素拷贝给本身 vector(v.begin(),v.end())构造函数将n个elem拷贝给本身 vector(n.elem)拷贝构造函数 vector(const vector vec)#includeiostream
using namespace std;
#includevectorvoid printVector(vectorint vec)
{for (vectorint::iterator it  vec.begin();it ! vec.end();it){cout  *it   ;}cout  endl;
}
void test1()
{//默认无参构造函数vectorint v1;for (int i  0;i  10;i){v1.push_back(i  1);}printVector(v1);// 通过区间方式进行构造vectorint v2(v1.begin(), v1.end());printVector(v2);//n个elem方式构造vectorint v3(4, 88);printVector(v3);//拷贝构造vectorint v4(v3);printVector(v4);
}int main()
{test1();system(pause);return 0;
}3.2.3vector赋值操作 
给vector容器赋值操作函数原型 重载等号操作符 vector operator(const vector vec)将[begin,end)区间中的数据拷贝赋值给本身 assign(beg,end)将n个element拷贝赋值给本身 assign(n,elem)//赋值 operatorvectorint v11;v11  v4;printVector(v11);//assignvectorint v12;v12.assign(v4.begin(), v4.end());printVector(v12);3.2.4vector容量和大小 
对vector容器的容量和大小操作函数原型 判断容器是否为空 empty()容器容量 capacity()返回容器中元素的个数 size()重新指定容器的长度为num若容器长度变长则以默认值填充新位置如果容器变短则末尾超出容器长度的元素被删除 resize(int num)重新指定容器的长度num若容器变长则elem值填充新位置如果容器变短则末尾超出容器长度的元素被删除 resize(int num,elem)cout  容量:  v12.capacity()  endl;// 4cout  容量:  v12.size()  endl;// 4v12.resize(8);cout  容量:  v12.capacity()  endl;// 8cout  容量:  v12.size()  endl;// 83.2.5vector插入和删除 
对vector容器进行插入、删除操作函数原型 尾部插入元素ele push_back(ele)删除最后一个元素 pop_back()迭代器指向位置pos插入元素ele insert(const_iterator pos,ele)迭代器指向位置pos插入count个元素ele insert(const_iterator pos,int count,ele)删除迭代器指向的元素 erase(const_iterator pos)删除迭代器从start到end之间的元素 erase(const_iterator start,const_iterator end)删除容器中所有元素 claer()v12.push_back(78);cout  容量:  v12.capacity()  endl;// 12cout  容量:  v12.size()  endl;// 9printVector(v12);//插入迭代器  v12.insert(v12.begin(), 10);printVector(v12); 
3.2.6vector数据存取 
对vector中的数据存取操作函数原型 返回索引idx所指的数据 at(int idx)返回索引idx所指的数据 operator[idx]返回容器中第一个数据元素 front()返回容器中最后一个数据元素 back()3.2.7vector互换容器 
实现两个容器内元素进行互换函数原型 将vec与本身的元素互换 swap(vec)//巧用swap收缩内存
v.resize(3);
vectorint(v).swap(v)3.2.8vector预留空间 
减少vector在动态扩展容量时的扩展次数函数原型 容器预留len个元素长度预留位置不初始化元素不可访问 reserve(int len)3.3deque容器 
3.3.1deque容器基本概念 
双端数组可以对头端进行插入删除操作deque与vector区别 vector对于头部的插入删除效率低数据量越大效率越低deque相对而言对头部的插入删除速度会比vector快vector访问元素时的速度会比deque快这和两者内部实现有关  deque内部工作原理 deque内部有一个中控器维护每段缓冲区中的内容缓冲区中存放的真实数据中控器维护的每个缓冲区的地址使得使用deque时像一片连续的内存空间  deque容器的迭代器也是支持随机访问的 
3.3.2deque构造函数 
deque容器构造函数原型 默认构造形式 dequeT depT构造函数将[beg,end)区间中的元素拷贝给本身 deque(beg,end)构造函数将n个elem拷贝给本身 deque(n,elem)拷贝构造函数 deque(const deque dep)#includeiostream
#includedeque
using namespace std;//添加const避免值被修改
void printDeque(const dequeint dep)
{for (dequeint::const_iterator it  dep.begin();it ! dep.end();it){cout  *it   ;}cout  endl;
}void test1()
{//默认构造dequeint dep;for(int i  0;i 10;i){dep.push_back(i  1);}printDeque(dep);dequeint dep2(dep.begin(), dep.end());printDeque(dep2);
}int main()
{test1();system(pause);return 0;
}3.3.3deque赋值操作 
给deque容器进行赋值函数原型 重载等号操作符 deque operato(const deque dep)将[beg,end)区间中的数据拷贝赋值给本身 assign(beg,end)将n个elem拷贝赋值给本身 assign(n,elem)3.3.4deque大小操作 
对deque容器大小进行操作函数原型 判断容器是否为空 empty()返回容器中元素的个数 size()重新指定容器的长度为num若容器变长则以默认值填充新位置如果容器变短则末尾超出容器长度的元素被删除 resize(num)重新指定容器的长度为num若容器变长则以elem值填充新位置如果容器变短则末尾超出容器长度的元素被删除 resize(num.elem)3.3.5deque插入删除 
向deque容器中插入删除元素函数原型 容器尾部添加一个元素 push_back(elem)在容器头部插入一个元素 push_front(elem)删除容器最后一个元素 pop_back()删除容器第一个元素 pop_front()在pos位置插入一个elem元素的拷贝返回新数据的位置 insert(const_iterator pos,elem)在pos位置插入n个elem数据无返回值 insert(const_iterator pos,n,elem)在pos位置插入[beg,end)区间的数据无返回值 insert(const_iterator pos,beg,end)清空容器的所有数据 clear()删除[beg,end)区间的数据返回下一个数据的位置 erase(beg,end)删除pos位置的数据返回下一个数据的位置 erase(const_iterator pos)//  在dep1前面插入dep2
dep1.insert(dep1.begin(),dep2.begin(),dep2.end())3.3.6deque数据存取 
对deque中的数据存取操作函数原型 返回所有idx所指的数据 at(idx)返回索引idx所指的数据 operator[]返回容器中第一数据元素 front()返回容器中最后一个数据元素 back()3.3.7deque排序 
利用算法实现对deque容器进行排序算法 对beg和end区间内元素进行排序 sort(iterator beg,iterator end)3.4案例 
3.5stack容器 
3.5.1stack基本概念 
stack是一种先进后出(First In Last Out,FILO)的数据结构它只有一个出口 栈中只有顶端的元素才可以被外界使用因此栈不允许有遍历行为栈中进入数据称为 ------- 入栈 push栈中弹出数据称为 ------- 出栈 pop 
3.5.3stack常用接口 
1.构造函数 
stack采用模板类实现stack对象默认构造函数 
stackT stk;拷贝构造函数 
stack(const stack stack)2.赋值操作 
重载等号操 
stack operator(const stack stack)3.数据存取 
向栈顶添加元素 
push(elem)从栈顶移除第一个元素 
pop()返回栈顶元素 
top()4.大小操作 
判断堆栈是否为空 
empty()返回栈的大小 
size()3.6queue容器 
3.6.1queue基本概念 queue是一种先进先出(First In First Out,FIFO)的数据结构它有两个出口   队列容器允许从一端新增数据另一端移除数据  队列中只有队头和队尾可以被外界使用因此队列不允许有遍历行为  队列中进数据称为 — 入队 push  队列中出数据称为 — 出队 pop  
3.6.2queue常用接口 
栈容器常用的对外接口 
1.构造函数 
queue采用模板类实现queue对象的默认构造形式 
queueT que;拷贝函数 
queue(const queue que)2.赋值操作 
重载等号操作符 
queue operator(const queue que)3.数据存取 
往队尾添加元素 
push(elem)从队头移除第一个元素 
pop()返回最后一个元素 
back()返回第一个元素 
front()4.大小操作 
判断堆栈是否为空 
empty()返回栈的大小 
size()3.7list容器 
3.7.1list基本概念 
将数据进行链式存储链表是一种物理存储单元上非连续的存储结构数据元素的逻辑顺序是通过链表中的指针链接实现的链表的组成 链表是由一系列结点组成每一个结点有一个存储数据元素的数据域和一个存储下一个结点地址的指针域 STL中的链表是一个双向循环链表 链表的存储方式并不是连续的内存空间链表list中的迭代器只支持前移和后移属于双向迭代器list的优点 采用动态存储分配不会造成内存浪费和溢出链表执行插入和删除操作十分方便修改指针即可不需要移动大量元素 list的缺点 链表灵活但是空间(指针域)和时间(遍历)额外消耗较大  
3.7.2list构造函数 
创建list容器函数原型 list采用模板类实现对象默认构造形式 listT lst;构造函数将[beg,end)区间中的元素拷贝给本身 list(beg,end)构造函数将n个elem拷贝给本身 list(n,elem)拷贝构造函数 list(const list lst)#includeiostream
#includelist
using namespace std;
void printList(const listint lst)
{for (listint::const_iterator it  lst.begin();it ! lst.end();it){cout  *it   ;}cout  endl;
}void test1()
{listint lst;lst.push_back(20);lst.push_back(22);lst.push_back(21);lst.push_back(29);lst.push_back(90);printList(lst);listint lst1(lst.begin(), lst.end());printList(lst1);listint lst2(5, 30);printList(lst2);listint lst3;lst3  lst;printList(lst3);
}int main() 
{test1();system(pause);return 0;
}3.7.3list赋值和交换 
给list容器进行赋值以及交换list容器函数原型 将[beg,end)区间中的数据拷贝赋值给本身 assign(beg,end)将n个elem拷贝给本身 assign(e,elem)重载等号操作符 list operator(const list lst)将lst与本身的元素互换 swap(lst)listint lst4;lst4.assign(lst.begin(), lst.end());printList(lst4);lst4.swap(lst2);printList(lst2);printList(lst4);3.7.4list大小操作 
对list容器的大小操作函数原型 返回容器中元素的个数 size()判断容器是否为空 empty()重新指定容器的长度为num若容器变长则以默认值填充新位置如果容器变短则末尾超出容器长度的元素被删除 resize(num)重新指定容器的长度为num若容器变长则以elem值填充新位置如果容器变短则末尾超出容器长度的元素被删除 resize(num,elem)3.7.5list插入和删除 
对list容器进行数据的插入和删除函数原型 在容器尾部加入一个元素 push_back(elem)删除容器最后一个元素 pop_back()在容器开头插入一个元素 push_front(elem)从容器开头移除第一个元素 pop_front()在pos位置插入elem元素的拷贝返回新数据的位置 insert(pos,elem)在pos位置插入n个elem数据无返回值 insert(pos,n,elem)在pos位置插入[beg,end)区间的数据无返回值 insert(pos,beg,end)移除容器的所有数据 clear()删除[beg,end)区间的数据返回下一个数据的位置 erase(beg,end)删除pos位置的数据返回下一个数据的位置 erase(pos)删除容器中所有与elem值匹配的元素 remove(elem)lst4.insert(lst4.begin(), 4, 22);printList(lst4);lst4.pop_back();printList(lst4);3.7.6list数据存取 
对list容器中数据进行存取(不支持随机访问)函数原型 返回第一个元素 front()返回最后一个元素 back()//验证迭代器是否支持随机访问
listint::iterator it  lst.begin();
it;
it--;
// it  it  1;//error,不支持随机访问3.7.7list反转和排序 
将容器中的元素反转以及将容器中的数据进行排序函数原型 反转链表 reverse()链表排序 sort()所有不支持随机访问迭代器的容器不支持用标准算法 
lst.sort()3.8set/multiset容器 
3.8.1set基本概念 
1.简介 
所有元素都会在插入时自动被排序 
2.本质 
set/multiset属于关联式容器底层结构是用二叉树实现 
3.set和multiset区别 
set不允许容器存中有重复的元素multiset允许容器中有重复的元素 
#includeiostream
using namespace std;
#includesetvoid printSet(const setint st)
{for(setint::const_iterator it  st.begin();it ! st.end();it){cout  *it   ;}cout  endl;
}void test()
{setint st;st.insert(10);st.insert(20);st.insert(50);st.insert(40);st.insert(30);st.insert(30);cout  遍历容器  endl;printSet(st);// 10 20 30 40 50
}int main() 
{test();system(pause);return 0;
}3.8.2set构造和赋值 
创建set容器以及赋值函数原型 构造 默认构造函数 setT st拷贝构造函数 set(const set st)赋值 重载等号操作符 set operator(const set st)3.8.3set大小和交换 
统计set容器大小以及交换set容器函数原型 返回容器中元素的数据 size()判断容器是否为空 empty()交换两个集合容器 swap()3.8.4set插入和删除 
set容器进行插入数据和删除数据函数原型 在容器中插入元素 insert(elem)清除所有元素 clear()删除pos迭代器所指元素返回下一个元素的迭代器 erase(pos)删除区间[beg,end)的所有元素返回下一个元素的迭代器 erase(beg,end)删除容器中值为elem的元素 erase(elem)setint::iterator it  st.begin();
it;
setint::iterator its  st.erase(it);
cout  下一个元素的迭代器  *its  endl;// 303.8.5set查找和统计 
对set容器进行查找数据以及统计函数原型 查找key是否存在若存在返回该键的元素的迭代器若不存在返回set.end() find(key)统计key的元素个数 count(key)setint::iterator it1 st.find(20);if (it1 ! st.end()){cout  找到元素  *it1  endl;}else{cout  未找到该元素  endl;}int num  st.count(30);cout  元素的个数:  num  endl;// 13.8.6set和multiset区别 
区别 set不可以插入重复数据而multisetset插入数据的同时会返回插入结果表示是否插入成功multiset不会检测数据因此可以插入重复数据  
3.8.7pair对组创建 
成对出现的数据利用对组可以返回两个数据两种创建方式pairtype,type p (value1,value2)
pairtype,type p  make_pair(value1,value2)#includeiostream
using namespace std;void test()
{//第一种方式pairstring, int p(Tom, 22);cout  姓名:  p.first  年龄:  p.second  endl;//第二种方式pairstring, int p2  make_pair(Jerry, 18);cout  姓名:  p2.first  年龄:  p2.second  endl;
}int main()
{test();system(pause);return 0;
}3.8.8set容器排序 
set容器默认排序规则为从小到大改变排序规则技术点 利用仿函数可以改变排序规则  
#includeiostream
#includedeque
#includealgorithm
using namespace std;//添加const避免值被修改
void printDeque(const dequeint dep)
{for (dequeint::const_iterator it  dep.begin();it ! dep.end();it){cout  *it   ;}cout  endl;
}void test1()
{//默认构造dequeint dep;for(int i  0;i 10;i){dep.push_back(i  1);}printDeque(dep);dequeint dep2(dep.begin(), dep.end());printDeque(dep2);sort(dep2.begin(), dep2.end());printDeque(dep2);
}int main()
{test1();system(pause);return 0;
}3.9map/multimap容器 
3.9.1map基本概念 
1.简介 
map中所有元素都是pairpair中第一个元素为key键值起索引作用第二个元素为value实值所有元素都会根据元素的键值自动排序 
2.本质 
map/multimap属于关联式容器底层结构使用二叉树实现 
3.优点 
可以根据key值快速找到value值 
4.map和multimap区别 
map不允许容器中重复key值元素multimap允许容器中重复key值元素 
3.9.2map构造和赋值 
对map容器进行构造和赋值操作函数原型 ma默认构造函数 mapT1,T2 mp;拷贝构造函数 map(const map mp)重载等号操作符 map operator(const map mp)mapstring,int mp;
mp.insert(pairstring,int (Tom,18)); 
3.9.3map大小和交换 
统计map容器的大小以及交换map容器函数原型 返回容器中元素的数目 size()判断容器是否为空 empty()交换两个集合 swap()3.9.4插入和删除 
map容器进行插入数据和删除数据函数原型 在容器中插入元素 insert(elem)清除所有元素 clear()删除pos迭代器所指的元素返回下一个元素的迭代器 erase(pos)删除区间[beg,end)的所有元素返回下一个元素的迭代器 erase(beg,end)删除容器中值为key的元素 erase(key)3.9.5map查找和统计 
对map容器进行查找数据以及统计数据函数原型 查找key是否存在若存在返回该键的元素的迭代器若不存在返回set.end() find(key)统计key的元素个数 count(key)3.9.6map容器排序 
map容器默认排序规则为按照key值进行 从小到大排序技术点 利用仿函数可以改变排序规则  #includeiostream
using namespace std;
#includemap
#includestringclass MyCompare 
{
public:bool operator()(string str1,string str2)const{return str1  str2;}
};void test()
{mapstring, int,MyCompare mp;//mp.insert(pairstring, int(数字化, 13));mp.insert(make_pair(数字化, 13));//同上mp.insert(make_pair(模块化, 31));mp.insert(make_pair(智能化, 20));mp.insert(make_pair(系统化, 8));mp.insert(make_pair(助手化, 22));for (mapstring, int::iterator it  mp.begin();it ! mp.end();it){cout  项目名称:   (*it).first  项目年限  it-second  endl;}
}int main()
{test();system(pause);return 0;
}