目录
建立通用的模板,提高代码复用性
·c++还有一种利用模板的泛型编程
建立函数,其返回值类型和形参类型用虚拟类型代表
template
- // 函数模板
- template<typename T> // 声明一个模板,T是通用数据类型
- void mySwap(T &a, T &b)
- {
- T temp = a;
- a = b;
- b = temp;
- }
-
- void test()
- {
- int a = 10;
- int b = 20;
- // 1.自动类型推导
- mySwap(a, b);
- mySwap<int>(a, b);
- // 2.显示指定类型
- cout << "a:" << a << endl;
- cout << "b:" << b << endl;
- }
将类型参数化
·自动类型推导:必须推导出一致的数据类型T
·模板必须确定出T的数据类型才可以使用
- // 交换函数模板
- template<class T>
- void myswap(T &a, T &b)
- {
- int temp = a;
- a = b;
- b = temp;
- }
- // 排序算法
- template<typename T> // 声明一个模板,T是通用数据类型
- void mySort(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]);
- }
- }
- }
-
- void test()
- {
- char chararr[] = "cabdjukadn";
- int num = sizeof(chararr) / sizeof(char);
- mySort(chararr, num);
- for (int i = 0; i < num; i++)
- {
- cout << chararr[i];
- }
- cout << endl;
- }
·普通函数调用时可以发生隐式类型转换
·函数模板调用时,若利用自动类型推导,不会发生隐式类型转换
·若利用显示指定类型的方式,可以发生隐式类型转换(建议使用)
·若函数模板和普通函数都可以实现,优先调用普通函数
·可通过空模板参数列表来强制调用函数模板
·函数模板可以发生重载
·若函数模板可以产生更好的匹配,优先调用函数模板
提供函数模板后不要提供普通函数,避免产生二义性
模板不是万能的。无法实现自定义数据类型的通用化,需要利用模板重载具体化数据类型
- // myCompare 为模板,进行重载
- template<> bool myCompare(Person &a,Person &b)
与函数模板大体一致
- // 类模板
- template<class Nametype,class Agetype>
- class Person
- {
- public:
- Person(Nametype name, Agetype age)
- {
- this->m_name = name;
- this->m_age = age;
- }
- Nametype m_name;
- Agetype m_age;
- };
·类模板中没有自动类型推导的方式
·类模板在模板参数列表中可以有默认参数
·普通成员函数一开始创建
·类模板中成员函数在调用时创建
类模板实例化出的对象,向函数传参的方式:
·指定传入的类型:直接显示对象的数据类型
- // 类模板对象做函数参数
- template<class 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 << endl;
- cout << "age:" << this->m_age << endl;
- }
- Nametype m_name;
- Agetype m_age;
- };
- // 1.指定传入类型
- void printPerson1(Person
int >&p) - {
- p.showPerson();
- }
- void test01()
- {
- Person
int>p("sun", 100); - printPerson1(p);
- }
·参数模板化:将对象中的参数变为模板进行传递
- // 2.参数模板化
- template<class Nametype,class Agetype>
- void printPerson2(Person
&p) - {
- p.showPerson();
- }
- void test02()
- {
- Person
int>p("zhu", 99); - printPerson2(p);
- }
·整个类模板化:将这个对象类型模板化进行传递
- // 3.整个类模板化
- template<class T>
- void printPerson3(T &p)
- {
- p.showPerson();
- }
- void test03()
- {
- Person
int>p("sha", 90); - printPerson3(p);
- }
·子类继承的父类为类模板时,子类在声明的时候,要指定父类T的类型,否则无法给子类分配内存
- // 类模板与继承
- template<class T>
- class Base
- {
- T m;
- };
- class son:public Base<int>
- {
-
- };
·若需灵活指定父类T类型,子类需变为类模板
- // 类模板与继承
- template<class T>
- class Base
- {
- T m;
- };
- template<class T1,class T2>
- class son:public Base
- {
- T1 obj;
- };
类外实现时,类内只写函数声明
- // 类模板成员函数类外实现
- template<class T1,class T2>
- class Person
- {
- public:
- Person(T1 name, T2 age);
- void show();
-
- T1 m_name;
- T2 m_age;
- };
- // 构造函数的类外实现
- template<class T1, class T2>
- Person
::Person(T1 name, T2 age) - {
- this->m_name = name;
- this->m_age = age;
- }
- template<class T1, class T2>
- // 成员函数类外实现
- void Person
::show() - {
- cout << "姓名:" << this->m_name << "年龄:" << this->m_age << endl;
- }
类模板中成员函数创建时机在调用阶段,导致分文件编写时链接不到
- void test()
- {
- Person
int>P("time", 20); - P.show();
- }
类的声明在头文件中,类的实现在源文件中。此时主函数中调用上述代码会报错。
解决方法1:直接包含.cpp源文件
- #include
- using namespace std;
- #include
- #include"Person.cpp"
解决方法2:将声明和实现写到同一个文件中,更改后缀名为.hpp
#include"Person.hpp"
全局函数类内实现:在类内声明友元
全局函数类外实现:提前让编译器得知全局函数的存在
- // 让编译器提前获取类外函数
- template<class T1, class T2>
- class Person;
-
- template<class T1, class T2>
- void PrintPerson(Person
p) - {
- cout << "姓名:" << p.m_name << "年龄:" << p.m_age << endl;
- }
- // 通过全局函数打印信息
- template<class T1,class T2>
- class Person
- {
- // 友元函数类外实现
- // 添加空模板的参数列表
- friend void PrintPerson<>(Person
p); - public:
- Person(T1 name, T2 age)
- {
- this->m_name = name;
- this->m_age = age;
- }
- private:
- T1 m_name;
- T2 m_age;
- };
在.hpp文件中编写类模板
- #pragma once
- #include
- using namespace std;
- #include
- // 通用数组类
- template<class T>
- class myArray
- {
- public:
- // 有参构造 参数 容量
- myArray(int capacity)
- {
- //cout << "有参构造调用" << endl;
- // 属性初始化
- this->m_Capacity = capacity;
- this->m_Size = 0;
- this->pAddress = new T[this->m_Capacity]; // 按照容量大小开辟堆区空间
- }
- // 拷贝构造(防止浅拷贝)
- myArray(const myArray& arr)
- {
- //cout << "拷贝构造调用" << endl;
- this->m_Capacity = arr.m_Capacity;
- this->m_Size = arr.m_Size; // 指针不能直接赋值,否则会产生浅拷贝
- // 深拷贝
- this->pAddress = new T[arr.m_Capacity];
- // 拷贝arr中数据
- for (int i = 0; i < this->m_Size; i++)
- {
- this->pAddress[i] = arr.pAddress[i];
- }
- }
- myArray& operator=(const myArray& arr)
- {
- //cout << "operator=调用" << endl;
- // 先判断堆区是否有数据,若有先释放
- 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];
- // 拷贝arr中数据
- for (int i = 0; i < this->m_Size; i++)
- {
- this->pAddress[i] = arr.pAddress[i];
- }
- }
- // 尾插法
- void pushBack(const T & val)
- {
- // 判断容量是否等于大小
- if (this->m_Capacity == this->m_Size)
- {
- return;
- }
- this->pAddress[this->m_Size] = val; // 在数组末尾插入数据
- this->m_Size++; // 更新数组大小
- }
- // 尾删法
- void popBack()
- {
- // 让用户无法访问末尾
- if (this->m_Size==0)
- {
- return;
- }
- this->m_Size--;
- }
- // 通过下标访问数组元素
- T& operator[](int index) // operator重载运算符[]
- {
- return this->pAddress[index];
- }
- // 返回数组容量
- int getCapacity()
- {
- return this->m_Capacity;
- }
- // 返回数组大小
- int getSize()
- {
- return this->m_Size;
- }
-
- // 析构函数
- // 释放堆区空间
- ~myArray()
- {
- //cout << "析构函数调用" << endl;
- if (this->pAddress != NULL)
- {
- delete[] this->pAddress;
- this->pAddress = NULL; // 置空防止野指针
- }
- }
- private:
- T * pAddress; // 指针指向堆区开辟的真实数组
- int m_Capacity; // 数组容量
- int m_Size; // 数组大小
- };
其中:构造函数为初始化、拷贝构造防止浅拷贝、operator=重载操作符防止浅拷贝、析构函数清空堆区内容。
源文件
- #include
- using namespace std;
- #include
- #include"myArray.hpp"
- void printIntArray(myArray<int>&arr)
- {
- for (int i = 0; i < arr.getSize(); i++)
- {
- cout << arr[i] << endl;
- }
- }
- void test()
- {
- myArray<int>arr1(5);
- for (int i = 0; i < 5; i++)
- {
- arr1.pushBack(i);
- }
- printIntArray(arr1);
- cout << "arr1的容量" << arr1.getCapacity() << endl;
- cout << "arr1的大小" << arr1.getSize() << endl;
-
- myArray<int>arr2(arr1);
- printIntArray(arr2);
- arr2.popBack();
- cout << "arr2尾删后的容量" << arr2.getCapacity() << endl;
- cout << "arr12尾删后的大小" << arr2.getSize() << endl;
- }
-
- int main()
- {
- test();
- system("pause");
- return 0;
- }
1.概念:STL(standard template library,标准模板库)
2.STL从广义上分为:容器、算法、迭代器
3.容器和算法间通过迭代器连接
1.容器:各类数据结构
2.算法:各类常用算法
3.迭代器:容器与算法间的桥梁
4.仿函数:行为类似函数
5.适配器:修饰容器或仿函数或迭代器接口
6.空间配置器:空间配置与管理
1.容器分为序列式容器(强调值的排序,序列式容器中每个元素均有固定位置)与关联式容器(二叉树结构,各元素间没有严格物理上的顺序关系)
2.算法分为质变算法(运算期间会更改区间元素内容)和非质变算法(运算期间不会更改区间元素内容)
3.迭代器种类
- #include
- using namespace std;
- #include
- #include
- #include
- // vector容器存放内置数据类型
- void myPrint(int val)
- {
- cout << val << endl;
- }
- void test()
- {
- // 创建vector容器,可认为是数组
- vector<int> v;
- // 向容器中插入数据
- v.push_back(10);
- v.push_back(1200);
- v.push_back(120);
-
- // 第一种遍历方式
- // 通过迭代器访问容器中的数据
- vector<int>::iterator itBegin = v.begin(); // 起始迭代器,指向容器中首个元素
- vector<int>::iterator itEnd = v.end(); // 结束迭代器,指向容器中末尾元素的下一个位置
- while (itBegin != itEnd)
- {
- cout << *itBegin << endl;
- itBegin++;
- }
- // 第二种遍历方式
- for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
- {
- cout << *it << endl;
- }
- // 第三种遍历方式,利用遍历算法
- for_each(v.begin(), v.end(), myPrint);
- }
- // vector容器存放自定义数据类型
- class Person
- {
- public:
- Person(string name, int age)
- {
- this->name = name;
- this->age = age;
- }
- string name;
- int age;
- };
-
- void test()
- {
- // 创建vector容器
- vector
v; - Person p1("a", 10);
- Person p2("b", 20);
- Person p3("c", 30);
-
- // 向容器中添加数据
- v.push_back(p1);
- v.push_back(p2);
- v.push_back(p3);
-
- // 通过迭代器访问容器中的数据
- for (vector
::iterator it = v.begin(); it != v.end(); it++) - {
- cout << "姓名:" <<(*it).name<< " 年龄:"<<(*it).age << endl;
- // 以下相同
- //cout << "姓名:" << it->name<< " 年龄:" << it->age << endl;
- }
- }
- // 存放自定义数据类型的指针
- void test01()
- {
- // 创建vector容器
- vector
v; - Person p1("a", 10);
- Person p2("b", 20);
- Person p3("c", 30);
-
- // 向容器中添加数据
- v.push_back(&p1);
- v.push_back(&p2);
- v.push_back(&p3);
-
- // 遍历
- for (vector
::iterator it = v.begin(); it != v.end(); it++) - {
- cout << "姓名:" << (*it)->name << " 年龄:" << (*it)->age << endl;
- }
- }
- // vector容器嵌套
- void test()
- {
- // 创建vector容器
- vector
int>> v; - // 创建内层容器
- vector<int> v1;
- vector<int> v2;
- vector<int> v3;
- for (int i = 0; i < 4; i++)
- {
- v1.push_back(i + 1);
- v2.push_back(i + 2);
- v3.push_back(i + 3);
- }
- // 创建外层容器
- v.push_back(v1);
- v.push_back(v2);
- v.push_back(v3);
- // 通过迭代器访问容器中的数据
- for (vector
int>>::iterator it = v.begin(); it != v.end(); it++) - {
- for (vector<int>::iterator vit = (*it).begin(); vit != (*it).end(); vit++)
- {
- cout << *vit;
- }
- cout << endl;
-
- }
- }
string本质上是个类,是一个char*型的容器。类内提供了多种成员方法
string(); 默认构造
string(const char* s); 使用字符串初始化
string(const string str); 使用一个string对象初始化另一个string对象
string(int n ,char c); 使用n个字符串c初始化
常用前三种方式赋值
- // 方法1
- string str1;
- str1 = "hello";
-
- // 方法2
- string str2;
- str2 = str1;
-
- // 方法3
- string str3;
- str3 = 'a';
-
- // 方法4
- string str4;
- str4.assign("hello");
-
- // 方法5
- string str5;
- str5.assign("hello", 4);
-
- // 方法6
- string str6;
- str6.assign(str5);
-
- // 方法7
- string str7;
- str7.assign(10, '7');
- // 方法1
- string str1 = "hello";
- str1 += "world";
-
- // 方法2
- string str2 = "!";
- str1 += str2;
-
- // 方法3
- string str3 = "hello";
- str3.append("world");
-
- // 方法4
- string str4 = "hello";
- str4.append("hello",4);
-
- // 方法5
- string str5 = "hello";
- str5.append(str2);
-
- // 方法6
- string str6;
- str6.append(str5,0,3);
- // 查找
- // 方法1
- string str1 = "hello";
- str1.find("l"); // 若存在返回1,否则返回-1
-
- // 方法2
- str1.rfind("l"); // rfind从右往左查,find查找顺序相反
-
- // 替换
- str1.replace(1,3,"11");
字符串以ASCii大小进行比较,相等返回0,大于返回1,小于返回-1
- // 字符串比较
- string str1 = "hello";
- string str2 = "hello";
- if (str1.compare(str2) == 0)
- {
- cout << "相等" << endl;
- }
- // 字符串存取
- string str = "hello world";
- // 方法1:通过[]访问单个字符
- for (int i = 0; i < str.size(); i++)
-
- {
- cout << str[i] << endl;
- }
- // 方法2通过at方式
- for (int i = 0; i < str.size(); i++)
- {
- cout << str.at(i) << endl;
- }
- // 字符串插入与删除
- string str = "hello world";
-
- str.insert(1, "11"); // 插入
-
- str.erase(1, 2); // 删除
- // 字符串子串获取
- string str = "hello world";
-
- string subStr = str.substr(1, 3);
vector与数组类似,称为单端数组;不同于数组是静态空间,vector可以动态扩展(寻找更大的内存空间,将源数据拷贝至新空间,并释放原空间)
vector容器的迭代器是支持随机访问的迭代器
创建vector容器
- vector<int> v1; // 无参构造
-
- vector<int> v2(v1.begin(), v1.end()); // 通过区间方式进行构造
-
- vector<int> v3(10, 100); // n个elem方式构造
-
- vector<int> v4(v3); // 拷贝构造
- // 无参构造
- vector<int> v1;
- // operator=
- vector<int> v2;
- v2 = v1;
- // assign
- vector<int> v3;
- v3.assign(v1.begin(), v1.end());
- // n个elem赋值
- vector<int> v4;
- v4.assign(10, 100);
swap可以收缩空间
- vector<int> v;
- for (int i = 0; i < 10; i++)
- {
- v.push_back(i);
- }
- cout << v.capacity() << endl;
- cout << v.size() << endl;
- vector<int>(v).swap(v);
- cout << v.capacity() << endl;
- cout << v.size() << endl;
减少vector在动态扩展容量时的扩展次数
双端数组,可以对头端进行插入删除操作
需包含算法头文件
对于支持随机访问的迭代器的容器(vector),都可利用sort算法直接对其排序。
- // 选手类
- class Person
- {
- public:
- Person(string name, int score)
- {
- this->m_name = name;
- this->m_score = score;
- };
- string m_name;
- int m_score;
- };
- // 创建选手
- void creatPerson(vector
&v) - {
- string nameSeed = "ABCDE";
- for (int i = 0; i < 5; i++)
- {
- string name = "选手";
- name += nameSeed[i];
- int score = 0;
-
- Person p(name, score);
- // 将创建的person对象,放入到容器中
- v.push_back(p);
- }
- }
- // 打分函数
- void setScore(vector
&v) - {
- for (vector
::iterator it = v.begin(); it != v.end(); it++) - {
- deque<int> d;
- for (int i = 0; i < 10; i++)
- {
- int score = rand() % 41 + 60;
- d.push_back(score);
- }
- // 排序
- sort(d.begin(), d.end());
- // 去除最高与最低分
- d.pop_back();
- d.pop_front();
- // 取平均分
- int sum = 0;
- for (deque<int>::iterator dit = d.begin(); dit != d.end(); dit++)
- {
- sum += *dit;
- }
- int avg = sum / d.size();
- // 赋值给选手
- it->m_score = avg;
- }
- }
- // 显示得分
- void showScore(vector
&v) - {
- for (vector
::iterator it = v.begin(); it != v.end(); it++) - {
- cout << "姓名:" << it->m_name << " 平均分:"<< it->m_score << endl;
- }
- }
stack是一种先进后出的数据结构,只有一个出口。栈不允许有遍历行为
queue是一种先进先出的数据接口,只有队头和队尾才可被访问,不可遍历。
·将数据进行链式存储
·链表是一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的。
·链表由一系列结点组成,结点一个是存储数据元素的数据域,另一个是村查下一个结点地址都指针域
·STL中的链表是一个双向循环链表
·可以对任意位置进行快速插入或删除元素,但遍历速度没有数组快,且占用空间比数组大
链表中的迭代器只支持前移和后移,属于双向迭代器;
list不能用[]与at方式访问元素,迭代器不支持随机访问
- // 类定义
- class Person
- {
- public:
- Person(string name,int age,int height)
- {
- this->m_name = name;
- this->m_age = age;
- this->m_height = height;
- }
- string m_name;
- int m_age;
- int m_height;
- };
- // 排序规则
- bool comparePerson(Person &p1, Person &p2)
- {
- if (p1.m_age == p2.m_age)
- {
- return p1.m_height > p2.m_height;
- }
- return p1.m_age < p2.m_age;
- }
- void test()
- {
- list
L; - // 准备数据
- Person p1("刘备", 35, 175);
- Person p2("曹操", 45, 180);
- Person p3("孙权", 40, 170);
- Person p4("张飞", 25, 190);
- Person p5("关羽", 35, 160);
- Person p6("赵云", 35, 200);
- // 插入数据
- L.push_back(p1);
- L.push_back(p2);
- L.push_back(p3);
- L.push_back(p4);
- L.push_back(p5);
- L.push_back(p6);
- for (list
::iterator it = L.begin(); it != L.end(); it++) - {
- cout << "姓名:" << (*it).m_name << " 年龄:" << (*it).m_age << " 身高:" << (*it).m_height<< endl;
- }
- // 排序
- cout << "排序后:" << endl;
- L.sort(comparePerson);
- for (list
::iterator it = L.begin(); it != L.end(); it++) - {
- cout << "姓名:" << (*it).m_name << " 年龄:" << (*it).m_age << " 身高:" << (*it).m_height << endl;
- }
- }
·所有元素在插入时被自动排序
·属于关联式容器,底层结构用二叉树实现
·不允许有重复元素
成对出现的数据,利用对组可以返回两个数据
- // 对组的创建
- pair
int>p1("tom", 20); - cout << p1.first << p1.second << endl;
- pair
int>p2 = make_pair("jerry", 30); - cout << p2.first << p2.second << endl;
可以利用仿函数改变排序规则
·内置数据类型排序
- // 仿函数
- class mycompare
- {
- public:
- bool operator()(int v1,int v2) // 第一个()代表重载符,第二个()代表函数参数列表
- {
- return v1 > v2;
- }
- };
- void test()
- {
- set<int, mycompare>s1;
- s1.insert(10);
- s1.insert(20);
- s1.insert(40);
- s1.insert(30);
- for (set<int>::iterator it = s1.begin(); it != s1.end(); it++)
- {
- cout << *it << " ";
- }
- cout << endl;
- }
·自定义数据类型排序
- class Person
- {
- public:
- Person(string name, int age)
- {
- this->m_name = name;
- this->m_age = age;
- }
- string m_name;
- int m_age;
- };
- class mycompare
- {
- public:
- bool operator()(const Person &p1, const Person &p2) // 第一个()代表重载符,第二个()代表函数参数列表
- {
- return p1.m_age > p2.m_age;
- }
- };
- void test()
- {
- // 自定义数据类型要指定排序规则
- set
s; - Person p1("tom", 24);
- Person p2("jarry", 34);
- Person p3("luffy", 25);
- Person p4("zoro", 14);
- Person p5("sam", 55);
-
- s.insert(p1);
- s.insert(p2);
- s.insert(p3);
- s.insert(p4);
- s.insert(p5);
-
- for (set
::iterator it = s.begin(); it != s.end(); it++) - {
- cout << it->m_name << " " << it->m_age <
- }
- }
3.9 map/multimap容器
1.map概念
·map中所有元素都是pair
·pair中首个元素为key(键值),起到索引作用,第二个元素为value(实值)
·所有元素都会根据元素的键值自动排序
·map/multimap属于关联式容器,底层结构式二叉树实现
·可以根据key值快速找到value值
·map中不允许有重复key值元素
2.map构造和赋值
数据插入时要使用对组
3.map大小和交换
4.map插入和删除
5.map查找和统计
6.map容器排序
利用仿函数可以改变排序规则
3.10 案例-员工分组
- // 创建员工类
- class Worker
- {
- public:
- string m_name;
- int m_salary;
- };
- void creatWorker(vector
&v) - {
- string workerName = "ABCDEFGHIJ";
- for (int i = 0; i < 10; i++)
- {
- Worker worker;
- worker.m_name = workerName[i];
- worker.m_salary = rand()%10000 + 10000; // 10000--19999
- v.push_back(worker);
- }
- }
- // 员工分组
- void setGroup(vector
&v, multimap<int, Worker> &m) - {
- for (vector
::iterator it = v.begin(); it != v.end(); it++) - {
- // 产生随机部门编号
- int deptId = rand() % 3; // 0 1 2
- m.insert(make_pair(deptId, *it));
- }
- }
- void showWorker(multimap<int, Worker> &m)
- {
- cout << "0号部门成员:" << endl;
- multimap<int, Worker>::iterator pos = m.find(0);
- int count = m.count(0);
- int index = 0;
- for (; pos != m.end() && index < count; pos++,index++)
- {
- cout << "姓名:" << pos->second.m_name << " 工资:" << pos->second.m_salary << endl;
- }
-
- cout << "1号部门成员:" << endl;
- pos = m.find(1);
- count = m.count(1);
- index = 0;
- for (; pos != m.end() && index < count; pos++, index++)
- {
- cout << "姓名:" << pos->second.m_name << " 工资:" << pos->second.m_salary << endl;
- }
-
- cout << "2号部门成员:" << endl;
- pos = m.find(2);
- count = m.count(2);
- index = 0;
- for (; pos != m.end() && index < count; pos++, index++)
- {
- cout << "姓名:" << pos->second.m_name << " 工资:" << pos->second.m_salary << endl;
- }
- }
4 STL函数对象
4.1 函数对象
1.函数对象概念
本质上是一个类
2.函数对象使用
- // 仿函数
- // 可以像普通函数一样调用,可以有参数值与返回值
- class myAdd
- {
- public:
- int operator()(int v1, int v2)
- {
- return v1 + v2;
- }
- };
- void test01()
- {
- myAdd a;
- cout << a(10, 10) << endl;
- }
- // 函数对象可以有自己的状态
- class myPrint
- {
- public:
- myPrint()
- {
- this->count = 0;
- }
- void operator()(string test)
- {
- cout << test << endl;
- this->count++;
- }
- int count; // 记录内部状态
-
- };
- // 函数对象可以作为参数传递
4.2 谓词
1.概念
2.一元谓词
- // 一元谓词
- // 仿函数
- class GreaterFive
- {
- public:
- bool operator()(int val)
- {
- return val > 5;
- }
- };
- void test()
- {
- vector<int> v;
- for (int i = 0; i <10 ; i++)
- {
- v.push_back(i);
- }
- // 查找是否存在大于5的数字
- vector<int>::iterator it = find_if(v.begin(), v.end(), GreaterFive());
3.二元谓词
- // 二元谓词
- // 仿函数
- class mycompare
- {
- public:
- bool operator()(int v1,int v2)
- {
- return v1 > v2;
- }
- };
- void test()
- {
- vector<int> v;
- v.push_back(10);
- v.push_back(30);
- v.push_back(20);
- v.push_back(40);
- v.push_back(50);
-
- sort(v.begin(), v.end(), mycompare());
- for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
- {
- cout << *it << endl;
- }
- }
4.3 内建函数对象
1.内建函数对象
需要添加头文件functional
2.算术仿函数
实现四则运算
- // 一元仿函数
- negate<int> n;
- cout << n(50) << endl;
- // 二元仿函数
- plus<int> p;
- cout << p(10, 20) << endl;
3.关系仿函数
4.逻辑仿函数
5 STL常用算法
5.1 常用遍历算法
·算法头文件:algorithm、functional、numeric
1.for_each
2.transform
搬运容器到另一个容器中,搬运前需要给目标容器开辟空间
5.2 常用查找算法
1.find
按值查找元素
若查找自定义数据类型,需在类中重载==运算符
2.find_if
按条件查找元素
3.adjacent_find
查找相邻重复元素
4.binary_search
查找指定元素是否存在
5.count
统计元素个数
6.count_if
按条件统计元素个数
5.3 常用排序算法
1.sort
2.random_shuffle
3.merge
4.reverse
5.4 常用拷贝和替换算法
1.copy
2.replace
3.replace_if
4.swap
5.5 常用算术生成算法
1.accumulate
2.fill
5.6 常用集合算法
1.set_intersection
2.set_union
3.set_difference
目标容器开辟空间需要从两个容器取较大值