template<class 类型参数1, class 类型参数2, ...>
返回值类型 函数模板名(调用形参1, 调用形参2), ...{
...
}
eg:
template<class T>
T Max(T x, Ty){
return x>y ? x:y;
}
T
已经是一种惯例,T
表示的是调用者在使用这个函数模板时指定的任意数据类型函数模板名<类型实参1,类型实参2,...>(调用实参1,...);
例如:
Max<int>(123,456);
Max<double>(12.3,45.6);
Max<string>("hello","wordl");
>
操作符的类型来实例化一个Max
函数模板,编译器将报错编译器对函数模板都会进行两次编译
templateT Max(T x, T y){...}
Max(123,456);
Max(123,456);
templateT Max(T x,T y){...}
template T Max(T x,T y){```}
Max(123,45.6)
//这种调用是错误的< >
强行通知编译器选择函数模板类模板并不是一个真正的类
template
class 类模板名 {
...
};
示例:
template
class CMath{
public:
A m_a;
B func(){...};
};
template <class 类型形参1,...>
返回值类型 类模板名 <类型形参1,...>::函数名(调用形参1, ...){
函数实现;
}
示例:
template<class A.class B>B CMath<A,B>::func(){
...;
}
2.1 使用类模板必须对类模板进行实例化(产生真正的类).
2.2 类模板本身并不代表一个确定的类型,(即不能用于定义对象),只有通过类型实参实例化成真正的类后才具备类的语义,即可以定义对象
例如CMath
示例:
#include
using namespace std;
template<class T>
class CMath{
public:
CMath(T const& t1, T const& t2):m_t1(t1),m_t2(t2){}
T sum();
// T sum(){
// return m_t1+m_t2;
// }
private:
T m_t1;
T m_t2;
};
template<class T>//帽子不能丢
T CMath<T>::sum(){//类模板并不是一个真正的类,不能用模板名引成员,只有类才可以引成员,可以使用未知类来引成员
return m_t1+m_t2;
}
int main(int argc,char* argv[]){
int i=9,j=1;
CMath<int> a(i,j);
cout<<a.sum()<<endl;
string s="hello ";
string s2="world";
CMath<string> s3(s,s2);
cout<<s3.sum()<<endl;
return 0;
}
2.3 类模板被实例化时类模板中的成员函数并没有实例化,只有成员变量和虚函数,成员函数只有在被调用时才会被实例化,即产生真正的成员函数,注意:成员虚函数除外
2.4某些类型虽然没有提供类模板所需要的全部功能,但是照样可以实例化类模板,只是不要调用那些没有提供功能的成员函数即可
C:
静态局部变量:声明周期:进程级别,可见性:本函数可见
静态全局变量:声明周期:进程级别,可见性:本文件内可见
C++:
静态成员变量:生命周期:进程级别,可见性:本文件可见
#include
using namespace std;
template<class T>
class A {
public:
static int m_i;
static T m_t;
int a;
static void print() {
cout << "m_i: " << &m_i << " " << "m_t: " << &m_t << endl;
}
};
template<class T> int A<T>::m_i = 0;
template<class T> T A<T>::m_t;
int main() {
A<int> a, b, c;
a.print();
b.print();
c.print();
A<double> d, e, f;
d.print();
e.print();
f.print();
return 0;
}
}
/* 打印结果
m_i: 0x55b291109154 m_t: 0x55b291109158
m_i: 0x55b291109154 m_t: 0x55b291109158
m_i: 0x55b291109154 m_t: 0x55b291109158
m_i: 0x55b29110915c m_t: 0x55b291109160
m_i: 0x55b29110915c m_t: 0x55b291109160
m_i: 0x55b29110915c m_t: 0x55b291109160
*/
示例
#include
using namespace std;
template
class Array{
public:
T& operator[](size_t i){
return m_arr[i];
}
private:
T m_arr[10];
};
int main (int argc,char**argv){
// Array a;
// for(int i=0;i<10;i++){
// a[i]=i+1;
// }
// for (size_t i = 0,count=10; i < count; i++)
// {
// /* code */
// cout< > c;
for (size_t i=0,count=10; i < count; i++)
{
/* code */
for (size_t j = 0; j < count; j++)
{
/* code */
c[i][j]=i+j;
}
}
for (size_t i=0,count=10; i < count; i++)
{
/* code */
for (size_t j = 0; j < count; j++)
{
/* code */
cout<
0+0=0 0+1=1 0+2=2 0+3=3 0+4=4 0+5=5 0+6=6 0+7=7 0+8=8 0+9=9
1+0=1 1+1=2 1+2=3 1+3=4 1+4=5 1+5=6 1+6=7 1+7=8 1+8=9 1+9=10
2+0=2 2+1=3 2+2=4 2+3=5 2+4=6 2+5=7 2+6=8 2+7=9 2+8=10 2+9=11
3+0=3 3+1=4 3+2=5 3+3=6 3+4=7 3+5=8 3+6=9 3+7=10 3+8=11 3+9=12
4+0=4 4+1=5 4+2=6 4+3=7 4+4=8 4+5=9 4+6=10 4+7=11 4+8=12 4+9=13
5+0=5 5+1=6 5+2=7 5+3=8 5+4=9 5+5=10 5+6=11 5+7=12 5+8=13 5+9=14
6+0=6 6+1=7 6+2=8 6+3=9 6+4=10 6+5=11 6+6=12 6+7=13 6+8=14 6+9=15
7+0=7 7+1=8 7+2=9 7+3=10 7+4=11 7+5=12 7+6=13 7+7=14 7+8=15 7+9=16
8+0=8 8+1=9 8+2=10 8+3=11 8+4=12 8+5=13 8+6=14 8+7=15 8+8=16 8+9=17
9+0=9 9+1=10 9+2=11 9+3=12 9+4=13 9+5=14 9+6=15 9+7=16 9+8=17 9+9=18
类模板中所有的类型参数都进行了特化即全局特化
类模板中一部分的类型参数进行了特化即局部特化
template<class T, class D>class CMath{...};
全局特化
全类特化
template<>class CMath<int, double>{...};
成员特化
template<>int CMath<int, double>::sum{...}
局部特化
全类特化
template<class T>class CMath<T,short>{...};
成员特化
template<class T>int class CMath<T,short>::sum(){...}
特化一个类模板可以特化该类模板的所有成员函数,相当于重写写了一个针对某种特定数据类型的具体类
声明形式:
template<>
class 类模板名 <类型参数1,...>{
...;
};
例如:
template<class CMath<char* const>{...};
针对char* const
修改上面CMath模板类
#include
#include
using namespace std;
template<class T>
class CMath{
public:
CMath(T const& t1, T const& t2):m_t1(t1),m_t2(t2){}
T sum(){
return m_t1+m_t2;
}
private:
T m_t1;
T m_t2;
};
//全类特化
template<>class CMath<char* const>{
public:
CMath(char* const& t1, char* const& t2):m_t1(t1),m_t2(t2){}
char* const sum(){
return strcat(m_t1,m_t2);
}
private:
char* const m_t1;
char* const m_t2;
};
int main(int argc,char* argv[]){
char c1[100]="hello ";
char c2[100]="world";
CMath<char* const> cc(c1,c2);
cout<<cc.sum()<<endl;
return 0;
}
类模板除了可以对整个类进行特化以外.可以只针对某部分成员函数进行特化,要点:帽子不能丢,类名引成员
声明形式
template<>
返回值类型 类模板名<类型参数1,...>::成员函数名(调用参数1,..){
...;
}
例如:
template<>
char* const CMath<char* const>::sum(...){
...;
}
示例:
#include
#include
using namespace std;
template<class T>
class CMath{
public:
CMath(T const& t1, T const& t2):m_t1(t1),m_t2(t2){}
T sum(){
return m_t1+m_t2;
}
private:
T m_t1;
T m_t2;
};
//成员特化
template<>
char* const CMath<char* const>::sum(){
return strcat(m_t1,m_t2);
}
int main(int argc,char* argv[]){
char c1[100]="hello ";
char c2[100]="world";
CMath<char* const> cc(c1,c2);
cout<<cc.sum()<<endl;
return 0;
}
hello world
至少有两个及两个以上的类型参数,才会有局部特化
类模板的局部特化,除非必要否则尽量不要特化,因为特化版本过多容易引发编译器匹配歧义
局部特化也有全局特化和成员特化
示例:
#include
#include
using namespace std;
template<class T,class D>
class CMath{
public:
static void foo(){
cout<<"1:CMath" <<endl;
}
};
//局部特化
template<class T>class CMath<T,short>{
public:
static void foo(){
cout<<"2:CMath" <<endl;
}
};
int main(int argc,char* argv[]){
CMath<int,double>::foo();
CMath<int,short>::foo();
return 0;
}
1:CMath
2:CMath
#include
#include
using namespace std;
template<class T,class D>
class CMath{
public:
static void foo(){
cout<<"1:CMath" <<endl;
}
};
//局部特化
template<class T>class CMath<T,short>{
public:
static void foo(){
cout<<"2:CMath" <<endl;
}
};
template<class T>class CMath<T,T>{
public:
static void foo(){
cout<<"3:CMath" <<endl;
}
};
template<class T,class D>class CMath<T*,D*>{
public:
static void foo(){
cout<<"4:CMath" <<endl;
}
};
int main(int argc,char* argv[]){
CMath<int,double>::foo();//1:CMath
CMath<int,short>::foo();//2:CMath
CMath<int,int>::foo();//3:CMath
//CMath::foo;//出现歧义,2和3
CMath<int *,double *>::foo();//4:CMath
//CMath::foo();//出现歧义,4和3
return 0;
}
#include
#include
#include
using namespace std;
template<class T,class D=short>class A{
public:
void print(){
cout<<"m_t:"<<typeid(m_t).name()
<<",m_d:"<<typeid(m_d).name()<<endl;
}
private:
T m_t;
D m_d;
};
int main(int argc,char* argv[]){
A<int,double> a;
A<int> a2;
a.print();//m_t:i,m_d:d
a2.print();//m_t:i,m_d:s
return 0;
}
int
类型size_t
类型#include
using namespace std;
template<class T,size_t S=10>
class Array{
public:
T& operator[](size_t i){
return m_arr[i];
}
size_t size(){
return S;
}
private:
T m_arr[S];
};
int main (int argc,char**argv){
Array<int,5> a;
for(int i=0;i<a.size();i++){
a[i]=i+1;
}
for(int i=0;i<a.size();i++){
cout<<a[i];
}
return 0;
}
12345
成员变量,但其类型是一个类模板实例化的未知类,那它才可以称之为模板型成员变量
例如:
template<class T>
class Array{
...;
};//类模板
template<class D>
class Sum{ //类模板
public: Array<D> m_s;//模板型成员变量
}
示例:
#include
using namespace std;
template<class T>
class Array{
public:
T& operator[](size_t i){
return m_arr[i];
}
private:
T m_arr[10];
};
template<class D> class Sum{
public:
Sum(Array<D>& a):m_s(a){}
D add(){
D d=0;
for(int i=0;i<10;i++){
d+=m_s[i];
}
return d;
}
private:
Array<D> m_s;//模板型成员变量
};
int main (int argc,char**argv){
Array<int> a;
for(int i=0;i<10;i++){
a[i]=i+1;
}
Sum<int> s(a);
cout<<s.add()<<endl;//55
}
模板型成员函数
类模板的成员函数模板
例如:
template<class T>
class CMath{
public:
template<class D>
void foo1(){//成员函数模板
...;
}
template<class D>
void foo2();
};
//类外实现:
template<class T>
template<class D>
void CMath<T>::foo2(){
....;
}
示例:
#include
using namespace std;
template<class T>
class CMath{
public:
template<class D>void foo(){//模板型成员函数
cout<<"CMath::foo()" <<endl;
}
template<class G>void foo2();
private:
};
//类外实现foo2
template<class T> //帽子不能对
template<class G> //帽子不能丢
void CMath<T>::foo2(){ //类名引成员
cout << "CMath::foo2()" <<endl;
}
int main (int argc,char**argv){
CMath<int> c;
c.foo<int>();//CMath::foo()
c.foo2<int>();//CMath::foo2()
return 0;
}
类模板中嵌套类模板
例如:
template<class X>
class A{
public:
template<class Y>
class B{//模板型成员类型
public:
....;
};
};
类外实现:
template<class X>
class A{
public:
template<class Y>
class B;
}
template<class X>
template<class Y>
class A<X>::B{
...;
};
示例:
#include
using namespace std;
template<class X>
class A{
public:
template<class Y>
class B{
public:
template<class Z>
class C;
};
private:
};
template<class X>
template<class Y>
template<class Z>
class A<X>::B<Y>::C{
public:
template<class T>void foo(){
cout << "A::B::C::foo()" <<endl;
}
};
int main (int argc,char**argv){
A<int>::B<int>::C<int> c;
c.foo<string>();//A::B::C::foo()
return 0;
}
类模板的模板形参也可以是类模板,也可以有缺省值
例如:
template<class T>
class Array{
...;
};
template < template<classD>class C=Array>class Sum{
...;
};
示例:
#include
using namespace std;
template<class T>
class Array{
public:
T& operator[](size_t i){
return m_arr[i];
}
private:
T m_arr[10];
};
template< class D,template<class M>class C=Array >
class Sum{
public:
Sum(Array<D>& a):m_s(a){}
D add(){
D d=0;
for(int i=0;i<10;i++){
d+=m_s[i];
}
return d;
}
private:
C<D> m_s;//模板型成员变量
};
int main (int argc,char**argv){
Array<int> a;
for(int i=0;i<10;i++){
a[i]=i+1;
}
Sum<int,Array> s(a);
cout<<s.add()<<endl;//55
}
typename
标识符,意在告诉编译器其后是一个类模板的嵌套使用示例:
#include
using namespace std;
class A{
public:
class B{
void foo(){
cout<<"A::B::foo()"<<endl;
}
};
};
template<class T>
void Func(){
//T::B b;//报错,编译器第一次编译时,会将B认为是T中的一个静态成员的调用
typename T::B b;
//A::B b;
b.foo();
}
int main(){
return 0;
}
<>
而报告编译错误template
关键字,意在告诉编译器其后是一个函数模板示例,编译器就可以正确理解<>
了示例
#include
using namespace std;
class A{
public:
template<class T>
void foo(){
cout<<"A::foo()"<<endl;
}
};
template<class D>
void Func(){
D d; //未知类定义的对象
//d.foo();//未知类型调用包含了"<>"报错
d.template foo<int>();
}
int main(){
return 0;
}
this
指针,原理是变成了未知类型调用,编译器第一次编译就会认为合理有效示例:
#include
using namespace std;
// int m_i;
// void foo(){}
//基 类模板
template<class T>
class Base{
public:
int m_i;
void foo(){
cout<<"Base::foo()" <<endl;
}
};
//子 类模板
template<class M,class D>//帽子写一块
class Derived:public Base<M>{
public:
void bar(){
// int m_i;
// void foo(){}
// m_i=100;//报错
// foo();//报错
/*解决1
Base::m_i=100;
Base::foo();
*/
///*解决2
this->m_i=100;
this->foo();
//*/
}
};
int main(){
return 0;
}
问题
基于以上两点,就会在模板实现中产生不一致的语法语义
解决方法
如果希望模板中所有类型参数的变量.无论是类类型还是基本类型都以缺省方式获得初始化,就必须对其进行缺省的缺省构造T()
#include
using namespace std;
class Integer{
public:
Integer():m_i(0){}
private:
int m_i;
friend ostream& operator<<(ostream& os,Integer const& that);
};
ostream & operator<<(ostream& os,Integer const& that){
return os<<that.m_i;
}
template<class T>
void Func(){
//T t;//当T为基本类型时,因没有进行初始化,t的值是随机的
T t();//基本类型使用零值进行初始化,类类型使用无参构造来初始化
cout<<"t="<<t<<endl;
}
int main(){
Func<double>();
Func<Integer>();
return 0;
}
类模板中的成员虚函数的实例化是在虚函数表生成之后,而虚函数表生成时就需要进行虚函数地址的绑定,但是虚函数此时并没有实际地址,因此发生了冲突
#include
using namespace std;
template<class T>
class Base {
public:
virtual void foo() {
cout << "base::foo" << endl;
}
private:
};
template<class M, class N>
class Derived : public Base<N> {
public:
virtual void foo() {
cout << "derived::foo" << endl;
}
};
int main() {
Derived<int, int> d;
Base<int> *b = &d;
b->foo(); //derived::foo
return 0;
}
成员函数模板的延迟编译,阻碍了虚函数表的静态构建
优缺点
数组结构
链表结构
总结
STL模板库 中所提供的容器类,结合了数组和链表的优缺点,是用户从诸如内存管理的细节中得以解脱(对数组和链表的操作进行了封装)
类似数组(内部是线性存储)支持下标访问,在尾部添加和删除元素效率高,中间执行添加和删除操作也支持,但是效率低
front()
/ back()
/ insert()
/ erase()
push_back()
/ pop_back()
/ empty()
/ clear()
size()
向量维护元素个数
resize()
设置向量元素个数
capacity()
获取向量容量
reserve()
设置向量的容量
#include
#include
#include
using namespace std;
class Student {
public:
explicit Student(string name = "") : m_name(std::move(name)) {}
Student(Student const &that) : m_name(that.m_name) {
cout << "用: " << that.m_name <<" "<<&that<<" "<< " 拷贝构造了: " << m_name << " " << this << endl;
}
~Student() {
cout << "析构了: " << m_name << " " << this << endl;
}
private:
string m_name;
};
int main() {
vector<Student> vs;
vs.push_back(Student("LiSi"));
// 用: LiSi 0x7ffeda273fc0 拷贝构造了: LiSi 0x557535dcbeb0
// 析构了: LiSi 0x7ffeda273fc0
vs.push_back(Student("Zs"));
// 用: Zs 0x7ffeda273fc0 拷贝构造了: Zs 0x557535dcc310
// 用: LiSi 0x557535dcbeb0 拷贝构造了: LiSi 0x557535dcc2f0
// 析构了: LiSi 0x557535dcbeb0
// 析构了: Zs 0x7ffeda273fc0
// vs.emplace_back(Student("LiSi"));
// vs.emplace_back(Student("Zs"));
getchar();
return 0;
// 析构了: LiSi 0x557535dcc2f0
// 析构了: Zs 0x557535dcc310
}
/*
* push_back()函数向容器中加入一个临时对象(右值元素)时,
* 首先会调用构造函数生成这个对象,然后条用拷贝构造函数将这个对象放入容器中, 最后释放临时对象。
* 但是emplace_back()函数向容器中中加入临时对象, 临时对象原地构造,没有赋值或移动的操作。
* */
#include
#include
#include
using namespace std;
void print(string const &str, vector<int> &v) {
vector<int>::iterator begin = v.begin();
vector<int>::iterator end = v.end();
cout << "----------" << endl;
cout << str << endl;
for (vector<int>::iterator it = begin; it != end; ++it) {
cout << *it << ' ';
}
cout << endl;
cout << "----------" << endl << endl;
}
//比较器
class CMP {
public:
bool operator()(int i, int j) {
return i > j;
}
};
int main() {
vector<int> vi;
for (int i = 0; i < 10; ++i) {
vi.push_back(i);
}
print("push_back:", vi);
// ----------
// push_back:
// 0 1 2 3 4 5 6 7 8 9
// ----------
vi.pop_back();
print("pop_back:", vi);
// ----------
// pop_back:
// 0 1 2 3 4 5 6 7 8
// ----------
vi.insert(vi.begin(), 111);
print("insert:", vi);
// ----------
// insert:
// 111 0 1 2 3 4 5 6 7 8
// ----------
vi.erase(vi.begin());
print("erase:", vi);
// ----------
// erase:
// 0 1 2 3 4 5 6 7 8
// ----------
//print("start:", vi);
cout << vi.empty() << endl;//0
CMP cmp;
sort(vi.begin(), vi.end(), cmp);
print("sort", vi);
// ----------
// sort
// 8 7 6 5 4 3 2 1 0
// ----------
return 0;
}
支持下标访问(头尾两端都可以添加/删除操作)
#include
#include
#include
using namespace std;
template<class T>
void print(string const &str, T &v) {
auto begin = v.begin();
auto end = v.end();
cout << "----------" << endl;
cout << str << endl;
for (auto it = begin; it != end; ++it) {
cout << *it << ' ';
}
cout << endl;
cout << "----------" << endl << endl;
}
//比较器
template<class C>
class CMP {
public:
bool operator()(C i, C j) {
return i > j;
}
};
int main() {
deque<int> de;
for (int i = 0; i < 10; ++i) {
de.push_front(100+i);
}
print("push_front",de);
// ----------
// push_front
// 109 108 107 106 105 104 103 102 101 100
// ----------
for (int i = 0; i < 10; ++i) {
de.push_back(10+i);
}
print("push_back",de);
// ----------
// push_back
// 109 108 107 106 105 104 103 102 101 100 10 11 12 13 14 15 16 17 18 19
// ----------
CMP<int> cmp;
sort(de.begin(),de.end(),cmp);
print("sort",de);
// ----------
// sort
// 109 108 107 106 105 104 103 102 101 100 19 18 17 16 15 14 13 12 11 10
// ----------
auto it = find(de.begin(),de.end(),101);
if (it!=de.end()){
de.erase(it);
}else{
cout<<"not find: "<<101<<endl;
}
print("find and erase 101",de);
// ----------
// find and erase 101
// 109 108 107 106 105 104 103 102 100 19 18 17 16 15 14 13 12 11 10
// ----------
return 0;
}
在任何位置添加和删除都很方便,不支持下标访问
void unique(void);
void sort(void);
通过<
比较大小templatevoid sort(LESS less);
通过比较器比较大小//将lst剪切到调用列表的pos前位置
template<class IT>void splice(IT pos, list& lst);
//将lst中的del指向的节点剪切到调用列表pos前位置
template<class IT>void splice(IT pos, list& lst, IT del);
//将lst[begin,end)部分的节点剪切到调用列表pos前位置
template<class IT>void splice(IT pos, list& lst, IT begin, IT end);
#include
#include
using namespace std;
template<class T>
void print(string const &str, T &v) {
auto begin = v.begin();
auto end = v.end();
cout << "----------" << endl;
cout << str << endl;
for (auto it = begin; it != end; ++it) {
cout << *it << ' ';
}
cout << endl;
cout << "----------" << endl << endl;
}
//比较器
template<class C>
class CMP {
public:
bool operator()(C const& i, C const& j) {
return i > j;
}
};
int main() {
list<int> li;
for (int i = 0; i < 10; ++i) {
li.push_front(i);
li.push_front(i);
}
for (int i = 0; i < 10; ++i) {
li.push_front(i);
}
print("init", li);
// ----------
// init
// 9 8 7 6 5 4 3 2 1 0 9 9 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 0 0
// ----------
//唯一化,只会删除相邻的重复节点
li.unique();
print("unique", li);
// ----------
// unique
// 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
// ----------
li.sort();
print("sort",li);
// ----------
// sort
// 0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9
// ----------
CMP<int> cmp;
li.sort(cmp);
print("sort with cmp",li);
// ----------
// sort with cmp
// 9 9 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 0 0
// ----------
li.unique();
print("unique2",li);
// ----------
// unique2
// 9 8 7 6 5 4 3 2 1 0
// ----------
list<int> lst;
for (int i = 0; i <10; ++i) {
lst.push_back(100+i);
}
print("lst is:",lst);
// lst is:
// 100 101 102 103 104 105 106 107 108 109
// ----------
li.splice(li.begin(),lst);
print("lst splice",lst);
// ----------
// lst splice
//
// ----------
print("li splice:",li);
// ----------
// li splice:
// 100 101 102 103 104 105 106 107 108 109 9 8 7 6 5 4 3 2 1 0
// ----------
return 0;
}
支持在一端存储和提取数据(压栈,弹栈)
stack<元素类型, [底层容器]> 堆栈对象(构造实参表)
vector
deque
list
自己实现的容器
push()
-> push_back()
pop()
-> pop_back()
top()
-> back()
size()
-> size()
empty()
-> empty()
clear()
-> clear()
#include
template<class T, class D=deque<T> >
class stack{
public:
void push(T data){
m_d.push_back(data);
}
vodi pop(){
m_d.pop_back();
}
private:
D m_d;//唯一底层容器
};
支持从前端提取,后端压入元素
queue<元素类型, [底层容器]> 队列对象(构造实参表)
deque
list
自己实现的容器
不可以是vector
push()
-> push_back()
pop()
-> pop_front()
back()
-> back()
size()
-> size()
front()
->front()
empty()
-> empty()
clear()
-> clear()
类似队列,但所提取的是具有最高优先级的元素(默认最大者优先)
prioriyt_queue<元素类型, [底层容器], [比较器类型]> 优先队列对象(构造实参表)
deque
)不可以是list
vector
deque
底层容器支持随机迭代比较器
参数,默认使用<
运算符push()
pop()
top()
size()
empty()
clear()
以key-value对的形式存储数据,以key的升序排列,key唯一(内部结构是红黑树)
map<键类型,值类型> 映射对象
映射的迭代器相当于指向pair对象的指针
template<class FIRST, class SECOND>
class pair{
public:
pair(FIRST const& f, SECOND const& s):first(f),seconf(s){}
FIRST first;//键
SECOND second;//值
};
insert(pair<FIRST, SECOND>(key,value)
insert(make_pair(key,value))
迭代器 = find(键) //失败返回终止迭代器,并非全局函数,而是成员函数
允许key重复出现的映射
表示一对多的逻辑关系,不支持下标运算符
multimap<键类型, 值类型> 多重映射对象;
没有value的映射
与向量等基本容器相比最大的优势是排重
定义:
set<键类型> 集合对象
没有value的多重映射
定义:
multiset<键类型> 多重集合对象;
iterator
/const_iterator
/reverse_iterator
/const_reverse_iterator
begin()
/ end()
begin()const
/ end()const
rebegin()
/ rend()
rebegin()const
/ rend()const