零蚀
函数模版
-
函数模版
当我们不知道要传入和返回的类型的时候我们可以定义一个模版,他可以根据需要来设置自己的类型,它不存在于函数区中,他不会和其他同名函数发生冲突。如果有普通函数,会优先执行普通函数。
函数模版并不是真正的函数,他只是一个模版,用来生成其满足格式的函数,与他相反对应的是具名函数。
template <typename T> T add(T a,T b){ return a+b; } int main() { std::cout << add(1.0,2.2) << std::endl; std::cout << add(11,22) << std::endl; return 0; }
多种模版类型如下,模版也是支持重载的。
template <typename T, typename V> T add(T a,V b){ return a+b; } template <class N, class M> N add(M a,N b){ return a+b; } int main() { std::cout << add('c',2.2) << std::endl; std::cout << add(11,22) << std::endl; return 0; }
-
可变参数
可变参数有两种类型,一个是initializer_list要求可变参数的类型都必须一致,而省略号的则不具备这些限制。
省略号
#include <stdarg.h> // ...不能统计到个数,要自己传个数 int add(int num, ...){ va_list vl; va_start(vl,num); int sum=0; for(int i=0;i<num;i++){ sum+=va_arg(vl,int); } va_end(vl); return sum; } int main() { std::cout << add(5,1,2,3,4,5) << std::endl; return 0; }
initializer_list
/** * * @param initializer_list<可变参数的参数> list * @return * list 提供了start和end */ void add(initializer_list<int> list){ for(auto p=list.begin();p<list.end();p++){ cout << *p << endl; } } int main() { add({1,2,3,4,5}); return 0; }
-
可变参数的函数模版
在模版函数里,可变参数是传递过来的是参数包形式,通常获取数据的方式是递归,每调用一次,参数就会少一个,最后将参数全部拿出来。
int func(){ return 0; } template <typename ... T> int func(int a,T ... b ){ //这里的...a是任意的复合类型的参数包。 //拆包 cout << a << endl; func(b...); return 0; } int main() { func(1,2,3); return 0; }
func由于必须有一个int a的实参,所以如果不写一个空参的函数,会由于没有检测到空参会报错。
递归图解
函数执行完会走出栈操作。
参数包解包的操作
容器
-
顺序容器
顺序容器是在容器内部,元素摆放是有顺序的,通常vector已经能满足大部分开发。这些数组item的存储空间都是连续的,当增删的时候为了保持数组的顺序,所以要移动顺序,所以增删慢查询快(vector也是),列表相反。
容器 描述 string 与vector相似,尾部插入删除数度快 array 固定大小的数组,支持快速的随机访问,不能添加和删除 vector 可变大小数组,支持快读访,在尾部之外的地方插入/删除速度慢 deque 双向队列,支持快速的随机访问,两端的插入删除速度快 forward 单向链表,只支持单项顺序访问,插入和删除快,查询慢 list 与单项列表不同,它是双向列表,其他一样 -
迭代器
所有的容器都有迭代器,迭代器可以对内容间接访问。
vector<int> vec{1,3,4,5}; auto begin=vec.begin(); auto end=vec.end(); // * 作用域base的返回值,用于解引用 cout << *(begin.base()+1) << endl; // * 是operator* 迭代器的运算符重载 cout << *(begin+1) << endl; // 获取最后一个也可以最后一个,end 表示末尾的 \0 cout << *(end-1) << endl;
-
关联容器
根据关键字来索引item的,c++中有两个关联容器:map & set
构建pair
#include <utility> // 键值对的类 pair<string,int> p; p.first="云梦栏"; p.second=11; pair<string,int> p1{"开了",10}; cout << p.first << endl;
构建map
map是一对一的关系,一个键对应一个值,如果想要一对多就要用到multimap,它允许一对多,它们都定义子在include
#include <map> // 这里不能map map1("",11)这样会类型匹配错误,构造里默认是char类型 // 源码两个参数构造:map(const key_compare& __comp, const allocator_type& __a) map<string,int> map1; //插入 map1.insert({"科技",11}); int age= map1["科技"]; cout << age << endl; // 遍历 for (auto i = map1.begin(); i != map1.end(); ++i) { // 这里的->也是运算符的重载 cout << i->first << ":" << i->second << endl; } cout << map1.size() << endl;
构建set
set是简单集合,并且元素不能重复,当知识想知道一个值是否存在的时候,set是最为有用的,set为不可重复的容器,multiset为可重复的容器。系统会自动给set里的元素进行排序,set中的元素不能直接改变,内部是采用了一种非常高效的的平衡检索二叉树:红黑树,也称RB树,RB树的统计性要好于一般的平衡二叉树。
set<int> s; s.insert(1); s.insert(1); s.insert(2); for (auto i = s.begin(); i != s.end(); i++) { cout << *i << endl; } // 1,2
🔗 前言
🔗 C++ 高级列表
🔗 NO.1 C++ 基础
🔗 NO.2 C++ 指针
🔗 NO.3 C++ 特殊函数
🔗 NO.4 C++ 重载&继承&lambda
🔗 NO.5 C++ 虚函数&智能指针
🔗 NO.6 C++ I/O
🔗 NO.8 C++ 常用函数&线程
🔗 NO.9 C++ QT 入门
🔗 NO.10 C++ QT 绘制&自定义组合控件
🔗 NO.11 C++ QT 绘制