9, 容器

Deque

双向队列

和vector类似, 新增加:

push_front 在头部插入一个元素

pop_front 在头部弹出一个元素

Deque和vector内存管理不同: 大块分配内存

Stack

先进后出结构 只有一个出口

只能访问顶端元素, 不允许遍历

支持操作:

push增加元素

pop移除元素

top获取顶端元素

实际底层使用Deque实现, 但也可以实际制定容器Container

Queue

先进先出结构, 两个出口

不允许遍历

支持操作:

push增加元素

pop移除元素

front获取最前端元素

back获取最后的元素

实际底层使用Deque实现, 但也可以实际制定容器Container

Map - 重点学习

关联容器, 存储对象为key/value pair

不允许重复key

map存储对象必须具备可排序性

类的声明: 

template < class _Kty, class _Ty, class _Pr = lass<_Kty>, class _Alloc = allocator < pair < const _Kty, _Ty> > > class map{…………};

注意:

1, 两个> > 之间是有一个空格

2, 其中默认使用lass定义排序行为, 所以我们可以自定义排序行为 - 仿函数实现

3, 注意各种class的顺序!!! 注意排序所使用的可以是在哪里!!!

初步认识仿函数:

1, 定义一个类

struct Employee{

Employee(string& s1): Name(s1){}

string Name;

};

2, 定义一个仿函数

struct ReverseId: public std::binary_function< int, int, bool>{

bool operator() (const int& key1, const int& key2) const {

return (key1 <= key2) ? false : true;

}

};

仿函数就是要重载()小括号操作符! ! !

使用例子:

3, 构建一个序列:

std::pair < int, Employee> item[3] = {

std::make_pair(1, Employee(“Tom”)),

std::make_pair(2, Employee(“Azm”)),

std::make_pair(3, Employee(“Jack”)),

};

4, 定义一个map,是一个按照我们制定排序方法的map

std::map < int, Employee, ReverseId > map1(item, item+3);

5, 在map中插入元素

方法1 : map1.insert(std::make_pair(4,Employee(“Jason”)));

方法2 : map1[5] = Employee(“Hellon”);

6, 删除元素

std::map < int, Employee>::iterator it = map1.begin();

map1.erase(it);

7, 使用[]操作符存取元素

Employee& e = map1[14];

e.SetName(“Wason”);

Multimap

类似map的关联容器

允许key重复

std::multimap < int, Employee, ReverseId > mm1(item, item+3);

如果插入一个重复的key=1的key:

map1.insert(std::make_pair(4,Employee(“Peter”)));

则:

mm1.count(4)得到2 表名其中有两个key为4的元素

Set

关联容器, 存储对象本身即是key也是value

不允许重复key

set对象本身具有可排序性

类的声明: 

template < class _Kty, class _Pr = lass <_Kty> , class _Alloc = allocator < pair< const _Kty> > >

class set {…………};

注意:

1,默认采用less作为排序行为, 可以使用仿函数自定义排序行为

2,存储对象必须具备operator < 行为

set初始化:

1, 定义一个类

struct Programmer{
Programmer(const int id, const std::wstring name):
Id(id), Name(name){ } void Print() const
{
std::wcout<<L"["<<Id<<L"]: "<<Name<<std::endl;
} int Id;
std::wstring Name;
};

2, 定义仿函数

a, 使用ID升序排序

struct ProgrammerIdGreater : public std::binary_function< Programmer, Programmer, bool>{
bool operator() (const Programmer& p1, const Programmer& p2) const {
return (key1 <= key2) ? false : true;
}
};

b, 使用Name来进行排序

struct ProgrammerNameComparer : public std::binary_function< Programmer, Programmer, bool>{
bool operator() (const Programmer& p1, const Programmer& p2) const {
return (p1.GetId() <= p2.GetId()) ? false : true;
}
};

set相关算法:

1, set_union

std::set < Programmer, ProgrammerIdGreater > dest;

std::insert_iterator < std::set < Programmer, ProgrammerIdGreater > > ii(dest, dest.begin());

std::set_union(ps1.begin(), ps1.end(), ps2.begin(), ps2.end(), ii, ProgrammerIdGreater());

将会把ps1和ps2合并到dest当中,这里将会依照给出的排序规则进行排序!

2, set_intersection

std::set < Programmer, ProgrammerIdGreater > dest;

std::insert_iterator < std::set < Programmer, ProgrammerIdGreater > > ii(dest, dest.begin());

std::set_intersection(ps1.begin(), ps1.end(), ps3.begin(), ps3.end(), ii, ProgrammerIdGreater());

将会把ps1和ps3中全部重复的元素提取出来放在dest中! 这里将会依照给出的排序规则进行排序!

3, set_difference

std::set < Programmer, ProgrammerIdGreater > dest;

std::insert_iterator < std::set < Programmer, ProgrammerIdGreater > > ii(dest, dest.begin());

std::set_intersection(ps1.begin(), ps1.end(), ps4.begin(), ps4.end(), ii, ProgrammerIdGreater());

将会把全部存在于ps1中但不存在于ps4中的元素提取出来放在dest中.

4, 修改set对象中非key成员:

std::set < Programmer, ProgrammerIdGreater >::iterator it = ps1.find(Programmer(L”Bill”, 4));

if( it != ps1.end() )

const_cast < Programmer&>(*it).SetName(L”Bill Gates”);

注意这里的 & 引用 , 如果不加& 那么也是可以通过编译, 但是这样都是修改一个临时对象而已! 并不会实际修改.

10, 仿函数适配器

目的: 将无法匹配的仿函数"套接"成可以匹配的型别

适配器: 

binder1st/binder2nd

mem_fun/mem_fun_ref

实在是太难解释binder1st的实际使用原理, 所以先暂时使用老师的ppt:

注意:

1, first_argument_type

2, 操作符()重载

3,实现顺序

4,find_if()内部实现

老师的写法相当复杂!

其实实际写法是:

std::vector < int > ::iterator it = std::find_if(v.begin(), v.end(), std::bind1st( std::not_equal_to < int >(), 0 ) );

这里的0对应上面的value, 即使用0来初始化first_argument_type .

而另外一个bind2nd适配器,是类似的.

区别在于Func操作的作用是 左值 还是 右值 !!

mem_fun/mem_fun_ref:

是用来适配对象的成员函数

比如: 

std::vector < Person* > v;

…在v中加入很多成员.

其中Person类有一个成员函数Print() 用于打印信息.

std::for_each( v.begin(), v.end(), &Person::Print );

如果一切顺利的话, 那v中的每个对象都会执行一遍Print()函数, 但很可惜的是, 这里无法编译通过.

因为for_each只接受: Function(Obj) 其中Function为全局函数, 这样的调用.

所以这个时候 牛X的 mem_fun适配器出现了!

std::for_each( v.begin(), v.end(), std::mem_fun(&Person::Print) );

这样就能完美执行!

实现原理…………………………….

= =!

嗯, 看老师的ppt吧:

如果vector中放的不是Person对象的指针,那么就使用mem_fun_ref适配

std::vector v;

…………………

std::for_each( v.begin(), v.end(), std::mem_fun_ref(&Person::Print) );

11,注意问题

1, 尽量使用算法,而不是手写for循环

即使是在delete销毁对象这样的情况下. 为了能够销毁对象, 我们需要专门定义一个struct DeleteElement对象并重载operator()

struct DeleteElement{

template

void operator()(const TElement* p)const {

delete p;

}

};

然后使用for_each来销毁容器中的对象:

std::for_each(v.begin(), v.end(), DeleteElement() );

2, 使用swap来对容器进行缩水

3, 建立指针的容器,而不是对象的容器.

否则会出现很多问题. 比如数据切割,当对象通过基类拷贝,那么派生部分将会被切割掉! (slicing)

拷贝也会造成额外的内存开销.

STL与泛型编程-学习2-GeekBand的更多相关文章

  1. stl源码学习(版本2.91)--list

    stl源码学习(版本2.91)--list 一,阅读list()构造函数的收获 1,默认构造函数的作用和被调用的时机 struct no{ no(int i){} //no(){ // std::co ...

  2. C++STL标准库学习笔记(三)multiset

    C++STL标准库学习笔记(三)multiset STL中的平衡二叉树数据结构 前言: 在这个笔记中,我把大多数代码都加了注释,我的一些想法和注解用蓝色字体标记了出来,重点和需要关注的地方用红色字体标 ...

  3. [GeekBand] STL与泛型编程(1)

    在C++语法的学习过程中,我们已经对模板有了基本的了解.泛型编程就是以模板为工具的.泛化的编程思想.本篇文章介绍了一些在之前的文章中没有涉及到的一些模板知识.泛型编程知识和几种容器.关于模板的一些重复 ...

  4. [GeekBand] STL与泛型编程(2)

    本篇文章在上一篇文章的基础上进一步介绍一些常用的容器以及STL的一些深入知识. 一. Stack和Queue 栈和队列是非常常用的两种数据结构,由deque适配而来.关于数据结构的知识这里就不在介绍了 ...

  5. [GeekBand] STL与泛型编程(3)

    本篇文章主要介绍泛型算法中的变易.排序.数值算法. 一. 变易算法 所谓变易算法是指那些改变容器中的对象的操作. 1.1 copy组 template <class InputIterator, ...

  6. STL与泛型编程-第一周笔记-Geekband

    1, 模板观念与函数模板 简单模板: template< typename T > T Function( T a, T b) {- } 类模板: template struct Obje ...

  7. STL源码学习----lower_bound和upper_bound算法

    转自:http://www.cnblogs.com/cobbliu/archive/2012/05/21/2512249.html 先贴一下自己的二分代码: #include <cstdio&g ...

  8. STL源码学习----lower_bound和upper_bound算法[转]

    STL中的每个算法都非常精妙,接下来的几天我想集中学习一下STL中的算法. ForwardIter lower_bound(ForwardIter first, ForwardIter last,co ...

  9. 【STL源码学习】STL算法学习之三

    第一章:前言 数量不多,用到的时候会很爽. 第二章:明细 STL算法中的又一个分类:分割:将已有元素按照既定规则分割成两部分.  is_partitioned 函数原型: template <c ...

随机推荐

  1. vba增删改查数据库

    你在EXCEL中增加一个列名为ID,后在VBA中写以下代码,并引用Microsoft ActiveX Data Objects 2.8后执行Public Sub 写入SQL2008()Dim cnn ...

  2. 【FHQ-Treap】P4146 序列终结者

    题意: 给定一个序列,支持区间加,区间反转,区间max询问 裸的平衡树题,这里采用FHQ-Treap 每个节点多记录一个max值和两个lazy_tag,暴力Push_Down即可(大常数选手) 打完这 ...

  3. JedisCluster获取key所在的节点

    JedisCluster获取key所在的节点 2019年11月9日17:34:55 准备 引入jedis的jar包,这个jar包里面包含了JedisCluster,可以用它来操作集群. <dep ...

  4. 什么是 Hexo?

    Hexo   文档 欢迎使用 Hexo,本文档将帮助您快速上手.如果您在使用过程中遇到问题,请查看 问题解答 中的解答,或者在 GitHub.Google Group 上提问. 什么是 Hexo? H ...

  5. ECharts (mark)

    首页 文档 下载 实例 社区 工具 关于 2.0 EN ECharts 特性 特性 丰富的可视化类型 多种数据格式无需转换直接使用 千万数据的前端展现 移动端优化 多渲染方案,跨平台使用! 深度的交互 ...

  6. 数据库的元数据抽取SQL

    一.数据库驱动类.端口.默认用户名密码 数据库 驱动 端口 用户名 密码 MySQL com.mysql.jdbc.Driver 3306 root root DB2 com.ibm.db2.jcc. ...

  7. ransformResourcesWithMergeJavaResForDebug问题

    错误内容: Error:Execution failed for task ':app:transformResourcesWithMergeJavaResForDebug'. > java.i ...

  8. node---处理post请求

    //nodejs 处理post请求 // 异步 const http =require('http') const server=http.createServer((req,res)=>{ i ...

  9. 钉钉小程序----使用阿里的F2图表

    在钉钉小程序中使用F2的图表遇见很多问题 不能点击或者点击错乱的问题还没有解决,因为我解决不了........................... ------------------------- ...

  10. 配置文件一mapper.xml

    <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-/ ...