头文件<set>
①数据自带排序②没有重复(数据的唯一性)
- set<int> setData; //默认方式 从小到大
- set<int, less<int>> setData2; //和默认方式一样
- set<int, greater<int>> setData3; //从大到小
setData.insert(temp);
- for (set<int>::iterator iter = setData.begin(); iter != setData.end(); iter++)
- {
- cout << *iter << " ";
- }
核心问题:重载
第一行的less<····>是作为第二个的默认参数(下为set原型)
而less即为从小到大 所以我们需要重载<号 (其余同理) (注:一定要是常属性参数+常函数)
- class wbm
- {
- public:
- wbm(string name,int age):name(name),age(age){}
- bool operator<(const wbm &temp)const
- {
- return name < temp.name;
- }
- void print()
- {
- cout << name << "\t" << age << endl;
- }
- protected:
- string name;
- int age;
- };
- void test_wbm_set()
- {
- wbm w1("wbm1", 11);
- wbm w2("wbm2", 22);
- wbm w5("wbm5", 55);
- wbm w4("wbm4", 44);
- wbm w3("wbm3", 33);
- wbm temptest("wbm3", 99);
- set<wbm> wbmset = { w1,w2,w3,w4,w5,temptest };
- for (auto v : wbmset)
- {
- v.print();
- }
- }
输出结果:(很显然,temptest没有被插入进去)->查重标准是按照重载写的<准则(按照name进行比较的。
只具有排序功能,不具有去重功能
(不同点在于,multiset仅排序)
- void testmultiset()
- {
- multiset<int> mulData;
- for (int i = 0; i < 10; i++)
- {
- mulData.insert(rand() % 10);
- //rand()%26+'A';
- //rand()%26+'a';
- }
- for (auto v : mulData)
- {
- cout << v << " ";
- }
- cout << endl;
- }
输出结果:0 1 2 4 4 4 7 8 8 9
头文件 #include<bitset>
管理二进制的容器,不需要传类型(只需要传一个长度->代表有多少个二进制位)
(详见F1微软在线文档,在网安和底层开发会很有用。)

以字符串的形式就是直接原封不动的去掉引号,变成二进制
以传入一个整数的形式,就是将该整数(十进制)转化为二进制再保存到容器中。
②flip():1和0的反转(~) all():检测每一个位是否都是1 any():检测是否有位含1
- void testmultiset()
- {
- //多个二进制位
- bitset<8> bData("11110000");
- cout << bData << endl;
- bData.flip(); //等效于~
- cout << bData << endl;
- cout << bData.all() << endl;
- cout << bData.any() << endl;
- cout << bData.size() << endl;
- cout << bData.none() << endl;
- bitset<8> num(7); //将7转化为二进制的形式保存在bitset的容器中。
- cout << num << endl;
- }
输出:
11110000
00001111
0
1
8
0
00000111
->称为数对类型(将两个数据绑定到一起)
实际上就是一个两个待实例化的模板结构体
访问方式:m_pair.first m_pair.second 分别访问第一二个绑定的元素
- template <class _Ty1, class _Ty2>
- struct MyPair
- {
- _Ty1 first;
- _Ty2 second;
- MyPair(_Ty1 first, _Ty2 second) :first(first), second(second) {}
- };
- //map存储的数据是一个数对类型
- void testPair()
- {
- pair<int, string> pData(1, "string");
- MyPair<int, string> myPData(1, "string");
- cout << pData.first << " " << pData.second << endl;
- }
①插入:
方式一:insert一个数对类型(两个数值,first是键,second是值)
- map<int,string> mapData;
- mapData.insert(pair<int,string>(1,"string"));
方式二:insert通过一个make_pair函数构建
- map<int,string> mapData;
- mapData.insert(make_pair<int,string>(3,"string3"));
方式三:单映射中,可以直接采用数组下标的方式进行插入
- map<int,string> mapData;
- mapData[-1]=string("string-1");
方式三的代码等效于:
mapData.insert(pair<int,string>(-1,"string-1"));
注:相同的键,是采用覆盖的方式(保留最后一次更新的值)
②遍历:
方式一:迭代器遍历
(注:这里的*iter是pair数对类型。)
- for(auto iter=mapData.begin();iter!=mapData.end();iter++)
- {
- cout<<iter->first<<" "<<iter->second<<endl;
- //*iter指的是pair类型。
- }
方式二:
- for(auto v:mapData)
- {
- cout<<v.first<<" "<<v.second<<endl;
- }
③删除erase():
传入参数(是需要删除值对应的键)
mapData.erase(1);
④其他创建方式(有一个默认比较准则参数)
- map<int,string> mapData;
- map<int ,string,less<int>> mapData1; //此创建方式,等同于第一行,从小到大。
- map<int,string,greater<int>>mapData2; //从大到小
⑤处理自定义数据类型:
核心还是写重载函数(默认是按照键的某个属性进行比较),所以应该当键是自定义数据类型的时候,需要对键进行重载,若是用的默认的less<>比较准则,那么重载的就应该是<号
(需要默认的构造函数,print()成员函数需要是const类型)
- class MM
- {
- public:
- MM() = default;
- MM(string name, int age) :name(name), age(age) {}
- void print() const
- {
- cout << name << "\t" << age << endl;
- }
- bool operator<(const MM& object)const
- {
- return this->name < object.name;
- }
- protected:
- string name;
- int age;
- };
- class Boy
- {
- public:
- Boy() = default;
- Boy(string name, int age) :name(name), age(age) {}
- void print() const
- {
- cout << name << "\t" << age << endl;
- }
- protected:
- string name;
- int age;
- };
- void testUserData()
- {
- map<MM, Boy> mbData;
- mbData[MM("小美", 19)] = Boy("小张", 29);
- mbData[MM("小美", 19)].print();
- mbData[MM("小丽", 20)] = Boy("小明", 18);
- cout << "配对信息:" << endl;
- for (auto v : mbData)
- {
- //容器管理自定义类型数据
- //v:pair<MM,Boy>
- //v.frist:MM
- //v.second:Boy
- v.first.print();
- v.second.print();
- }
- }
更好管理资源
例: 在加载图片资源的时候,就直接用img[键]去对应相应的资源即可。(相比数组来说,这个下标是没有任何要求。)
- #include<grapghic.h>
- map<string,IMAGE*> ima;
- img["墙"]=new IMAGE;
- img["路"]=new IMAGE;
- putimage(0,0,img["墙"]);
- putimage(0,0,img["路"]);
多重映射,没有什么限制,什么样对应关系都可以插入到映射中,因为存在相同的键,所以不能采用下标法
基本同单映射,除了不能用下标法。
(注:find函数找到就返回,即返回找到的第一个)
- void testmultimap()
- {
- //多重映射,没有什么限制,什么样对应关系都可以插入到映射中
- //因为存在相同的键,所以不能采用下标法
- multimap<int, string> mulData;
- mulData.insert(pair<int, string>(1, "string"));
- mulData.insert(pair<int, string>(12, "string1"));
- mulData.insert(pair<int, string>(2, "string"));
- mulData.insert(pair<int, string>(3, "string"));
- mulData.insert(make_pair<int, string>(3, "string"));
- for (auto v : mulData)
- {
- cout << v.first << "\t" << v.second << endl;
- }
- }
输出:
1 string
2 string
3 string
3 string
12 string1
头文件:#include <initializer_list>

像这样的容器,初始化由后面的给的数据决定,构造函数的写法原理?
initializer_list对象(迭代器)可以存储大括号内的所有数据,并且可以一一赋值给容器中,对应的位置
①写一个类来简单模仿其实现的原理
②写一个函数来简单模仿传入多个参数的情况。
- #include <array>
- #include <list>
- #include <vector>
- #include <iostream>
- #include <initializer_list>
- using namespace std;
- class MM
- {
- public:
- MM(string a, string b, string c) :a(a), b(b), c(c) {}
- MM(const initializer_list<string>& list)
- {
- for (auto iter = list.begin(); iter != list.end(); iter++)
- {
- cout << *iter << endl;
- }
- }
- protected:
- string a;
- string b;
- string c;
- };
- void print(initializer_list<int> list)
- {
- for (auto iter = list.begin(); iter != list.end(); iter++)
- {
- cout << *iter << " ";
- }
- cout << endl;
- }
-
- int main()
- {
- array<int, 3> arrData = { 1,2,3 };
- vector<int> vecData1 = { 1,2,3,4 };
- vector<int> vecData2 = { 1,2,3,4,5 };
- MM mm1 = { "string1","string2","string3" };
- MM mm2 = { "string1" };
- MM mm3 = { "string1","string2" };
- initializer_list<int> listOne = { 1,2,3,4,5 };
- initializer_list<int> listTwo = { 1,2,3 };
- print({ 1 });
- print({ 1,2 });
- print({ 1,2,3,4 });
- print({ 1,2,3,4,5 });
- return 0;
- }
#include<tuple>
把任何类型的一系列数据当做一组来处理+自动增长
- //方式一:
- tuple<string,int,int,string> wbmInfo={"bmw",18,1001,"23123"};
- //方式二:
- tuple<double,double,double>wbmscore=make_tuple(99,22,33);
- //方式三:
- tuple<string,string>value=forward_as_tuple("阿杰","阿明");
以后结构体数组的偷懒写法:
tuple<string,int,int,string> array[3];
(不能用for循环,必须是常量)
- tuple<string,int,int,string> wbmInfo={"BMW",18,1001,"2312"};
- //get方法,不能用for循环
- cout<<get<0>(wbmInfo)<<"\t";
- cout<<get<1>(wbmInfo)<<"\t";
- cout<<get<2>(wbmInfo)<<"\t";
- cout<<get<3>(wbmInfo)<<"\t";
(有点类似于流操作)
- tuple<string,int,int,string> wbmInfo={"BMW",18,1001,"2312"};
- //tie方式访问数据
- string name;
- int age;
- int num;
- string tel;
- tie(name,age,num,tel)=wbmInfo;
- cout<<name<<"\t"<<age<<"\t"<<num<<"\t"<<tel<<endl;
将两个tuple连接起来: tuple_cat(参数1,参数2)
- tuple<string,int,int,string> wbmInfo={"bmw",18,1001,"23123"};
- tuple<double,double,double>wbmscore=make_tuple(99,22,33);
- auto res=tuple_cat(wbmInfo,wbmscore);
//...Args代表一个参数包
//1.如何通过参数包定义变量 Args ...args
//2.如何使用参数包 args... one
/*参数包的展开:
1.递归的方式,自动做一个参数包的剥离过程
2.采用列表方式进行剥离参数*/
方式一:递归展开实现代码
- #include<iostream>
- using namespace std;
-
- //递归终止函数
- template <class _Ty>
- void print(_Ty data)
- {
- cout << data<<endl;
- }
-
- template <class _Ty,class ...Args>
- void print(_Ty data,Args ...args)
- {
- cout << data << "\t";
- print(args...);//递归的方式,自身调用自身。
- }
-
- int main()
- {
- print(1, 2, 3, 4, "string", 12.3);
-
- return 0;
- }
方式二:采用列表(可增长)or数组方式进行剥离参数
- template <class _Ty, class ...Args>
- void printdata(_Ty data)
- {
- cout << data << "\t";
- }
- template<class ...Args>
- void printArgs(Args ...args)
- {
- //(printdata(args),0) 这是一个逗号表达式,返回的是最后一个式子的值
- initializer_list<int>{(printdata(args), 0)...};
- //也可以用数组做 等效于
- //int array[]={(printdata(args), 0)...};
- cout << endl;
- }
-
- int main()
- {
- printArgs(1, 2, 3, 4, "string", 12.3);
-
- return 0;
- }
printdata()是中间解析函数,负责展开打印。列表数据重复调用,(,)逗号表达式,先运行printdata再将0赋值给列表。...每次调用都会剥离分离1个出来。