目录
一、迭代器
基本概念
(1)内置迭代器的使用
(2)自己模拟迭代器的实现
(3)流型迭代器
二、lambda表达式
(1)基本概念
(2)捕获方式的区别
三、仿函数 包含头文件functional
基本概念
使用
四、函数适配器 包含头文件functional
(1)普通函数绑定
(2)类内成员函数绑定
(3)占位符表示原来的参数去第几位
五、函数包装器 包含头文件functional
(1)包装普通函数
(2)包装成员函数和静态函数
(3)包装仿函数
(4)更替参数顺序
迭代器:本质类中类,核心运算符重载
迭代器的分类
正向迭代器:iterator
begin()
end()
反向迭代器reverse_iterator
rbegin()
rend()
常正向迭代器 const_iterator
cbegin()
cend()
常反向迭代器const_reverse_iterator
crbegin()
crend()
按功能分类
正向迭代器
双向迭代器
随机访问迭代器
容器中迭代器分类 一般连续性内存都可用迭代器访问
容器名 迭代器类型
array 随机访问
vector 随机访问
deque 随机
stack、queue、priority_queue 不支持
list 双向
set/multiset 双向
map、multimap 双向
迭代器的辅助函数
移动 advance(iterator iter,n)
间距 distance(iterator begin,iterator end)
交换 iter_swap(iterator first iterator second)
#include<vector> int main() { vector<int> data = { 1,2,3,4,5,6,7,8,9 }; vector<int>::iterator iter; //对象模仿指针的行为 for (iter = data.begin();iter != data.end();iter++) { cout << *iter << " "; } cout << endl; //迭代器一般都是++操作无--操作 auto rIter = data.rbegin(); for (;rIter != data.rend();rIter++) { cout << *rIter << " "; } cout << endl; //区别在于常无法去修改数据 vector<int>::const_iterator c_iter; for (c_iter = data.cbegin();c_iter != data.cend();c_iter++) { cout << *c_iter << " "; } cout << endl; return 0; }
通过重载运算符的方式,将对象当指针使用
//节点 template<class _Ty> struct Node { _Ty data; Node<_Ty>* next; Node<_Ty>(_Ty data) :data(data), next(nullptr) {} //用作插入 Node<_Ty>(_Ty data, Node<_Ty>* next) : data(data), next(next) {} }; //链表 内部包含类中类iterator template<class _Ty> class My_List { public: My_List() { curSize = 0; } //插入节点 void push_front(int data) { if (curSize == 0) { frontNode = new Node<_Ty>(data); tailNode = frontNode; } else { frontNode = new Node<_Ty>(data, frontNode); } curSize++; } void print() { Node<_Ty>* pMove = frontNode; while (pMove != nullptr) { cout << pMove->data << " "; pMove = pMove->next; } } //迭代器 class iterator { public: iterator(Node<_Ty>* pMove=nullptr) :pMove(pMove) {} //由于用临时变量赋值,使用拷贝构造 iterator(const iterator& object) :pMove(object.pMove) {} bool operator!=(const iterator& object) const { return this->pMove != object.pMove; } iterator operator++(int) { pMove = pMove->next; return iterator(pMove); } _Ty operator*() { return pMove->data; } protected: Node<_Ty>* pMove; }; iterator begin() { return iterator(frontNode); } iterator end() { return iterator(nullptr); } protected: Node<_Ty>* frontNode; Node<_Ty>* tailNode; int curSize; }; void testList() { My_List<int> list; list.push_front(1); list.push_front(2); list.push_front(3); list.print(); My_List<int>::iterator iter = list.begin(); for (;iter != list.end();iter++) { cout << *iter << " "; } cout << endl; }
特殊迭代器(流型迭代器) 一般用在辅助打印
输出流型(两种构造方式)
ostream_iterator<_Ty> iter(ostream* out)
ostream_iterator<_Ty> iter(ostream& out,char* str)
输出流型迭代器赋值运算,就是把数据打印
输入流型(两种构造方式)
//构造无参对象,是错误流(输入错误类型返回错误)
istream_iterator<_Ty> iter //*运算等效cin
istream_iterator<_Ty> iter(istream& in)
#include<vector> void test1() { ostream_iterator<int> iter(cout); iter = 123;//打印到屏幕上 //一般作为别的函数的参数 在打印数据后面 ostream_iterator<int> iter2(cout,"欧拉欧拉"); iter2 = 1432; vector<int> data = { 1,2,3,4 }; //等效打印 copy(data.begin(), data.end(), ostream_iterator<int>(cout, "\t")); //输入流型 cout << "测试:" << endl; istream_iterator<int> end; istream_iterator<int> in(cin); vector<int> inputData; //反复输入 直到输入类型错误 while (in != end) { inputData.push_back(*in); ++in;//改变位置 使其能够重复输入 } for (auto v : inputData) { cout << v << " "; } cout << endl; }
就是一个返回函数指针的表达式
注意,它的定义和返回函数指针是一起的
组成部分 mutable:是否可以修改 exception:是否有异常
[捕获方式](函数参数)mutable exception->函数返回类型{函数体}
int Max(int a,int b)
{
return a>b?:a,b;
}//完整写法
int(*pMax)(int,int)=[](int a,int b)mutable noexcept->int{return a>b?:a,b;}
省略写法:中间描述词均可以省略
auto ppMax=[](int a,int b){return a>b?:a,b;}
//只需要短暂性局部使用 相当于函数定义声明 //定义函数指针 int(*pMax)(int a, int b) = nullptr; //函数实现 auto pp = [](int a, int b) {return a > b ? a : b;}; //直接调用 cout << pp(1, 3); cout << [](int a, int b) {return a > b ? a : b;}(1, 3) << endl;
捕获方式(函数使用外部变量的方式)
[=] 值的方式捕获:如果在函数中修改不会影响到外部变量
[&] 引用的方式捕获:同步到外部变量
[this] 类的方式:捕获类中数据成员
[] 不捕获任何变量
组合方式
[=,&] x用引用的方式,其余用值的方式
class MM { public: void print() {//表示捕获的是类内的数据 [this] {cout << name << " " << age << endl;}(); } protected: string name="mo"; int age=12; }; int main() { int data = 10101;//无参可以省略括号 //1.用值的方式:在lambda不能充当左值,函数1调用不会因为值的改变而改变 //即外界值在改变也不会影响函数 auto pData = [=] {cout << data << endl;}; pData(); data = 8080; pData(); //2.lambda可以改变值,并且会因为值的改变而改变 auto pData2 = [&] {cout << data << endl;}; //3.this方式 MM mm; mm.print(); //特殊 结合auto 类似函数模板 auto pAuto = [](auto a, auto b)->auto{return a > b ? a : b;}; cout << pAuto(1, 3); return 0; }
仿函数 类模仿函数调用行为
实质:无名对象调用重载的函数
一般情况,仿函数做排序准则 或者一些算法的计算准则
关键在于重载()
标准库中的仿函数
算术类
关系类
逻辑类
选择、证明、投射等
#include<map> class Sum { public: int operator()(int a, int b)const { return a + b; } protected: }; int main() {//自定义实现 //重载()的调用 Sum s; //显示调用 cout <<"显示调用"<< s.operator()(1, 3) << endl; cout << "隐式调用" << s(1, 3) << endl; //类模仿调用的行为 也可用Sum{}(1,3) 主要起标识作用 cout << "无名对象" << Sum()(1, 3) << endl; //库内部分例子 //算术 cout << plus<int>{}(1, 3) << endl; //关系 map<int, less<int>> map1; map<int, greater<int>> map2; //逻辑类 cout << logical_and<int>{}(1, 3);//&& return 0; }
bind函数绑定
以下面例子为例 Max函数有两个参数 ,print函数传入的pMax只有一个参数
使用bind给Max绑定一个参数再传入print
int Max(int a, int b) { return a > b ? a : b; } void print(int(*pMax)(int), int a) { pMax(a); } int main() { //只是单纯绑定一个参数 并未改变函数指针类型 //std::placeholders::_1占位符 //绑定的函数指针,占位符,参数设置 auto pMax = bind(Max, std::placeholders::_1, 100);//把第二个参数置为100 cout << pMax(1); cout << pMax(1, 2);//完成绑定后 使用绑定值第二个参数无效 return 0; }
class Test { public: void print(int a, int b, int c) { cout << a << " " << b << " " << c << endl; } }; void testClass() { Test test; auto testFunc = bind(&Test::print, test, std::placeholders::_1, std::placeholders::_2, 100); //此时调用不需要对象 直接调用 testFunc(1, 3); }
void printData(int a, Test b, string str) { cout << " 调用成功" << endl; } //通过占位符,调整参数位置 形成不同调用形态 //占位符表示原来的参数去第几位 1去第三位 Test()去第1位 "as"去第二位 void testExUser() { auto testFunc = bind(printData, std::placeholders::_3, std::placeholders::_1, std::placeholders::_2); printData(1, Test(), "as"); testFunc(Test(), "as", 1); }
一旦函数被包装,函数包装器可以替换函数指针直接调用
函数包装器实例化传参:function<函数返回值类型(参数类型)>
int Max(int a, int b) { cout << "包装普通函数" << endl; return a > b ? a : b; } int main() {//int返回值类型 (int,int)参数类型 function<int(int, int)> funcMax(Max); cout << funcMax(1, 3) << endl; return 0; }
class MM { public: void print(int a) { cout << "包装成员函数" << endl; } static void printStatic() { cout << "包装静态成员函数" << endl; } }; int main() { MM mm; function<void(int)> func(bind(&MM::print, &mm, std::placeholders::_1)); func(1); function<void()> funcS(MM::printStatic); funcS(); return 0; }
class MM { public: }; class Test { public: void operator()(string str) { cout << str << endl; } }; int main() { Test test; function<void(string)> func = test; func("包装仿函数"); return 0; }
class MM { public: }; void printData(int a, MM mm, string str) { cout << "bind与function结合" << endl; } void testFuncBind() { function<void(string, int, MM)> pf = bind(printData, std::placeholders::_2, std::placeholders::_3, std::placeholders::_1); pf("as", 1, MM()); }