C++ STL——C++容器的共性和相关概念
注:原创不易,转载请务必注明原作者和出处,感谢支持!
注:内容来自某培训课程,不一定完全正确!
一 STL容器共性机制
STL容器所提供的值都是值(value)寓意,而非引用(reference)寓意,也就是说当我们给容器中插入元素的时候,容器内部实施了拷贝动作,将我们要插入的元素再另行拷贝一份放入到容器中,而不是将原数据元素的引用放入容器中,也就是说我们提供的元素必须能够被拷贝。
(1)除了queue和stack之外,每个容器都提供可返回迭代器的函数,运用返回的迭代器就可以访问元素。
(2)通常STL不会抛出异常,需要使用者传入正确参数
(3)每个容器都提供了一个默认构造函数和默认的拷贝构造函数。
(4)大小相关的方法:size()返回容器中元素的个数,empty()判断容器是否为空
二 STL容器的使用场合
vector | deque | list | set | multiset | map | multimap | |
---|---|---|---|---|---|---|---|
典型内存结构 | 单端数组 | 双端数组 | 双向链表 | 二叉树 | 二叉树 | 二叉树 | 二叉树 |
可随机存取 | 是 | 是 | 否 | 否 | 否 | 对key而言:是 | 否 |
元素搜索速度 | 慢 | 慢 | 非常慢 | 快 | 快 | 对key而言:快 | 对key而言:快 |
元素插入和删除 | 尾端 | 头尾两端 | 任何位置 | - | - | - | - |
(1)vector容器的使用场景:比如软件历史操作记录的存储。
(2)deque的使用场景:比如排队购票系统,对排队者的存储可以采用deque,支持头端的快速移除,尾端的快速添加。
vector和deque的比较:
- vector.at()比deque.at()效率高,比如vector.at(0)是固定的,deque的开始位置却是不固定的。
- 如果有大量的释放操作的话,vector花的时间更少,这和二者的内部实现有关。
- deque支持头部的快速插入和删除,这是deque的优点。
(3)list的使用场景:比如公交乘客的存储,随时可能有乘客下车,支持频繁的不确定位置元素的移除。
(4)set的使用场景:比如对手机游戏的个人得分记录的存储,存储要求从高分到低分的顺序排列。
(5)map的使用场景:比如按ID号存储十万个用户,想要快速通过ID查找对应的用户,二叉树的查找效率就体现出来了。
三 函数对象
重载函数调用操作符的类,其对象常被称为函数对象(function object),即它们是行为类似函数的对象,也叫仿函数(functor),其实就是重载“()”操作符,使得类对象可以像函数那样调用。
注意:
(1)函数对象(仿函数)是一个类,不是一个函数
(2)函数对象重载了“()”操作符使得它可以像函数一样调用
假定某个类有一个重载的operator(),而且重载的operator()要求获取一个参数,我们就将这个类称为“一元仿函数(unary functor)”;相反,如果重载的operator()要求获取两个参数,我们就将这个类称为“二元仿函数(binary functor)”。
下面是函数对象的应用实例。
// 仿函数
class MyPrint
{
public:
MyPrint() { cnt = 0; }
void operator()(int val)
{
cout << val << endl;
++cnt;
}
unsigned getCnt() { return cnt; }
private:
unsigned cnt;
};
void Test1()
{
// 函数对象可以像普通函数那样调用
// 函数对象可以像普通函数那样接受参数
// 函数对象超出了函数的概念,函数对象可以保存函数的调用状态
MyPrint PRINT;
PRINT(10);
// 打印调用次数,使用函数对象可以避免使用全局变量
cout << "调用次数:" << PRINT.getCnt() << endl;
}
void Test2()
{
vector<int> v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
v.push_back(40);
MyPrint PRINT = for_each(v.begin(), v.end(), MyPrint());
cout << "调用次数:" << PRINT.getCnt() << endl;
}
你虽然避免了使用全局变量,但是却要求共用PRINT对象?
四 谓词
谓词是指普通函数或者重载的operator()返回值是bool类型的函数对象(仿函数)。如果operator()接受一个参数,那么叫做一元谓词,如果接受两个参数,那么叫做二元谓词,谓词可以作为一个判断式。
举例:
一元函数对象:for_each
一元谓词:find_if
二元函数对象:transform
二元谓词:sort
五 内建函数对象
STL内建了一些函数对象。分为:
(1)算术类函数对象
(2)关系运算符类函数对象
(3)逻辑运算类函数对象
这些仿函数所产生的对象,用法和一般函数完全相同,当然我们还可以产生无名的临时对象来履行函数的功能。使用内建函数对象,需要引入头文件#include <functional>
6个算术类函数对象,除了negate是一元运算,其他都是二元运算。
template<class T> T plus<T> // 加
template<class T> T minute<T> // 减
template<class T> T multiplies<T> // 乘
template<class T> T divides<T> // 除
template<class T> T modulus<T> // 取模
template<class T> T negate<T> // 取反
6个关系运算类函数对象,每一种都是二元运算。
template<class T> bool equal_to<T> // 等于
template<class T> bool not_equal_to<T> // 不等于
template<class T> bool greater<T> // 大于
template<class T> bool greater_equal<T> // 大于等于
template<class T> bool less<T> // 小于
template<class T> bool less_equal<T> // 小于等于
逻辑运算类函数对象,not为一元运算,其余为二元运算
template<class T> bool logical_and<T> // 逻辑与
template<class T> bool logical_or<T> // 逻辑或
template<class T> bool logical_not<T> // 逻辑非
六 函数对象适配器
函数对象适配器是完成一些配接工作,这些配接工作包括绑定(bind),否定(negate)以及对一般函数或成员函数的修饰,使其成为函数对象。
bind2st:将参数绑定为函数对象的第一个参数
bind2nd:将参数绑定为函数对象的第二个参数
not1:对一元函数对象取反
not2:对二元函数对象取反
ptr_fun:将普通函数修饰成函数对象
mem_fun:修饰成员函数
mem_fun_ref:修饰成员函数
函数适配器的应用案例。
struct MyPrint : public binary_function<int, int, void>
{
void operator()(int val, int add) const
{
cout << "val = " << val << " add = " << add << " val + add = " << val + add << endl;
}
};
// 仿函数适配器 bind1st bind2nd 绑定适配器
void Test1()
{
vector<int> v;
for (int i = 0; i < 10; ++i)
{
v.push_back(i);
}
// for_each()在位置3只能填入一个参数,如果需要传入多个参数
// 那么你需要用到绑定适配器,绑定适配器的作用是将二元函数对象
// 转变成一元函数对象。
int add = 200;
for_each(v.begin(), v.end(), bind2nd(MyPrint(), add));
// bind1st,将add的值200绑定为第一个参数val
// bind2nd,将add的值200绑定为第二个参数add
}
// 仿函数适配器 not1 not2 取反适配器
struct MyCompare : public binary_function<int, int, bool>
{
// 从大到小排序
bool operator()(int v1, int v2) const
{
return v1 > v2;
}
};
struct MyPrint2
{
void operator()(int v) const
{
cout << v << " ";
}
};
// 大于5
struct MyGreater5 : public unary_function<int, bool>
{
bool operator()(int v) const
{
return v > 5;
}
};
void Test2()
{
vector<int> v;
for (int i = 0; i < 10; ++i)
{
v.push_back(rand() % 100 + 10);
}
for_each(v.begin(), v.end(), MyPrint2());
cout << endl;
sort(v.begin(), v.end(), not2(MyCompare()));
for_each(v.begin(), v.end(), MyPrint2());
cout << endl;
// 如果对二元谓词取反,用not2
// 如果对一元谓词取反,用not1
// 使用not1()将条件由大于5改为小于等于5
vector<int>::iterator ret = find_if(v.begin(), v.end(), not1(MyGreater5()));
if (ret != v.end())
{
cout << *ret << endl;
}
else
{
cout << "没有找到!" << endl;
}
}
// 仿函数适配器 ptr_fun
void MyPrint3(int val, int add)
{
cout << "val = " << val << " add = " << add << endl;
}
void Test3()
{
vector<int> v;
for (int i = 0; i < 10; ++i)
{
v.push_back(i);
}
// 无法直接对函数MyPrint3()进行参数绑定
// for_each(v.begin(), v.end(), MyPrint3);
// 把普通函数适配成函数对象,再进行参数绑定
for_each(v.begin(), v.end(), bind2nd(ptr_fun(MyPrint3), 10));
}
// 成员函数适配器 mem_fun mem_fun_ref
class Person
{
public:
Person(int age, int id) : age(age), id(id) {}
void show()
{
cout << "age = " << age << " id = " << id << endl;
}
public:
int age;
int id;
};
void Test4()
{
// 如果容器中存放的对象或者对象指针,我们for_each算法
// 打印的时候调用类自己提供的打印函数
vector<Person> v;
Person p1(10, 20), p2(30, 40), p3(50, 60), p4(70, 80);
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
v.push_back(p4);
// 没有提供额外的打印函数,调用Person自己的成员函数show()
// 格式: &类名::函数名
for_each(v.begin(), v.end(), mem_fun_ref(&Person::show));
cout << endl << endl;
// 存储的是对象指针,用mem_fun
vector<Person *> v1;
v1.push_back(&p1);
v1.push_back(&p2);
v1.push_back(&p3);
v1.push_back(&p4);
for_each(v1.begin(), v1.end(), mem_fun(&Person::show));
// 如果存放的是对象,使用mem_fun_ref
// 如果存放的是对象指针,使用mem_fun
}
C++ STL——C++容器的共性和相关概念的更多相关文章
- c++复习:STL之容器
1 STL的string 1 String概念 string是STL的字符串类型,通常用来表示字符串.而在使用string之前,字符串通常是用char*表示的.string与char*都可以用来表示字 ...
- [C++ STL] 各容器简单介绍
什么是STL? 1.STL(Standard Template Library),即标准模板库,是一个高效的C++程序库. 2.包含了诸多常用的基本数据结构和基本算法.为广大C++程序员们提供了一个可 ...
- C++ STL vector容器学习
STL(Standard Template Library)标准模板库是C++最重要的组成部分,它提供了一组表示容器.迭代器.函数对象和算法的模板.其中容器是存储类型相同的数据的结构(如vector, ...
- STL List容器
转载http://www.cnblogs.com/fangyukuan/archive/2010/09/21/1832364.html 各个容器有很多的相似性.先学好一个,其它的就好办了.先从基础开始 ...
- STL之容器适配器queue的实现框架
说明:本文仅供学习交流,转载请标明出处,欢迎转载! 上篇文章STL之容器适配器stack的实现框架已经介绍了STL是怎样借助基础容器实现一种经常使用的数据结构stack (栈),本文介绍下第二种STL ...
- STL的容器算法迭代器的设计理念
1) STL的容器通过类模板技术,实现数据类型和容器模型的分离. 2) STL的迭代器技术实现了遍历容器的统一方法:也为STL的算法提供了统一性. 3) STL的函数对象实现了自定义数据类型的算法运算 ...
- stl之容器、迭代器、算法几者之间的关系
转自:https://blog.csdn.net/bobodem/article/details/49386131 stl包括容器.迭代器和算法: 容器 用于管理一些相关的数据类型.每种容器都有它的优 ...
- STL Queue 容器
STL Queue 容器 Queue简介 queue是队列容器,是一种“先进先出”的容器. queue是简单地装饰deque容器而成为另外的一种容器. # ...
- STL stack 容器
STL stack 容器 Stack简介 stack是堆栈容器,是一种“先进后出”的容器. stack是简单地装饰deque容器而成为另外的一种容器. #include <s ...
随机推荐
- python笔记:学习设置Python虚拟环境+配置 virtualenvwarpper+创建Python3.6的虚拟环境+安装numpy
虚拟环境它是一个虚拟化,从电脑独立开辟出来的环境.就是借助虚拟机docker来把一部分内容独立出来,我们把这部分独立出来的东西称作“容器”,在这个容器中,我们可以只安装我们需要的依赖包,各个容器之间互 ...
- Redis使用总结-基础篇
年底的时候开始尝试在重构的项目中使用redis,现在项目稳定运行也有一段时间了,这里做一下阶段性总结. 一.简介 首先,redis是什么意思呢,官方文档的FAQ里给出了答案:It means REmo ...
- string::assign
string (1) string& assign (const string& str); substring (2) string& assign (const strin ...
- MySQL基准测试和sysbench工具
参考https://www.cnblogs.com/kismetv/archive/2017/09/30/7615738.html 一.基准测试的作用 sysbench是一个开源的.模块化的.跨平台的 ...
- duilib学习领悟(1)
学习duilib已经有一段时间,一直没时间写总结,今天得出空来,写写心得体会! 由于本人知识有限,若有错误地方,望批评指正.多谢.! 初识duilib 刚开始接触duilib的时候,觉的他好神奇,整个 ...
- win10 出现 No AMD graphics driver is installed or the AMD driver is not functioning properly .....
原因:win10的自动更新的功能没有关闭,更新有时候会出现显卡驱动更新不及时出现的问题. 解决方法一:使用 驱动人生(或者等等....) 进行升级驱动. 解决方法二:手动升级. 1.打开设备管理器 2 ...
- 用vs2013开启一个C拖控件的项目
visual studio作为一款集成开发环境备受青睐,笔者尤其喜爱它的拖控件功能,程序员应该追求业务逻辑和实际功能的优化,而不是把时间消耗在编写窗体和按钮上 笔者曾翻阅中关村图书大厦,西单图书大厦, ...
- Codeforces Round #452 (Div. 2) 899E E. Segments Removal
题 OvO http://codeforces.com/contest/899/problem/E Codeforces Round #452 (Div. 2) - e 899E 解 用两个并查集(记 ...
- 【ArcCatalog】
1.添加文件夹链接文件夹链接的添加删除操作 2.新建/删除数据库(1)新建个人地理数据库(.mdb)(2)新建文本地理数据库(.gdb) 3.新建/删除要素数据集(1)要素数据集属性: 常规--XY坐 ...
- contents() 查找匹配元素内部所有的子节点(包括文本节点)。如果元素是一个iframe,则查找文档内容
contents() V1.2概述 查找匹配元素内部所有的子节点(包括文本节点).如果元素是一个iframe,则查找文档内容 示例 描述:大理石平台检定规程 查找所有文本节点并加粗 HTML 代码 ...