body, table{font-family: 微软雅黑; font-size: 10pt}
table{border-collapse: collapse; border: solid gray; border-width: 2px 0 2px 0;}
th{border: 1px solid gray; padding: 4px; background-color: #DDD;}
td{border: 1px solid gray; padding: 4px;}
tr:nth-child(2n){background-color: #f8f8f8;}

适配器:
  适配器相当于提供了一个接口,使得某些不适用于特定对象的方法可以被该对象所用,适配器形象的功能图解如所示,图中,容器或函数对象无法直接应用于算法,因此,必须有一种中间过渡机制来实现两者的匹配,这就是适配器,本质上,适配器是使一事物的行为类似于另一事物的行为的一种机制。
容器适配器:
1、容器适配器可以看作是对容器的封装,使其具有某些特殊的功能。容器适配器让一种已存在的容器类型采用另一种不同的抽象类型的工作方式实现,只是发生了接口转换而已。标准库提供了三种序列容器适配器:        
                stack(deque,list)、
                queue(deque,list)、        
                priority_queue(vector, deque)。
2、所有适配器都定义了两个构造函数:默认构造函数用于创建空对象,而带一个容器参数的构造函数将参数容器的副本作为其基础值。
3、默认的stack和queue都基于deque容器实现,而priority_queue则在vector容器上实现。在创建适配器时,通过将一个顺序容器指定为适配器的第二个类型参数,可覆盖其关联的基础容器类型。例如,下述代码创建的ob栈是基于vector实现的:stack<int, vector<int> > ob;
#include<iostream>
#include<vector>
#include<stack>
#include<string>
using namespace std;
int main()
{
        stack<int,vector<int> > ob1; //使用vector取代其默认的deque做为stack的实现基础
        cout<<ob1.size()<<endl;
        for(int i=0;i!=10;++i)
        {
                ob1.push(i);
        }
        cout<<ob1.size()<<endl;
        cout<<ob1.top()<<endl;
        ob1.pop();
        cout<<ob1.top()<<endl;
        cout<<"********"<<endl;

        stack<string,vector<string> > ob2;
        for(char i=65;i!=91;++i)
        {
                string tmp = string(1,i);
                ob2.push(tmp);
        }
        cout<<ob2.top()<<endl;
        ob2.pop();
        cout<<ob2.top()<<endl;
        return 0;
}

#include <iostream>
#include <queue>
using namespace std;
int main()
{
        queue<int> queInt;
        for(int idx = 0;idx < 10; ++idx)
        {
                queInt.push(idx);     //入队
                cout<< queInt.back() <<" 入队"<<endl;     //取队尾元素
        }
        cout<<queInt.size()<<" 个元素已经入队"<<endl;
        while(!queInt.empty())
        {
                cout<< queInt.front() <<" 出队"<<endl;    //取队头元素
                queInt.pop();    //出队
        }
        cout<< queInt.size()<<endl;
        return 0;
}
#include <iostream>
#include <queue>
using namespace std;
//采用的是"堆排序"进行元素的调整,默认情况下,比较函数是"<" 符号,堆顶的元素要与新进来的元素进行比较,如果为true,则将堆顶的元素放到堆底,新进来的元素放到堆顶;然后进行堆的调整

//出队从大到小
int main()
{
        int arr[10]={0,1,3,2,5,6,9,8,7,4};
        priority_queue<int> pqueInt;
        for(int idx = 0;idx != 10; ++idx)
        {
                pqueInt.push(arr[idx]);
                cout<< pqueInt.top() <<"是优先级别最高的"<<endl;
        }
        while(!pqueInt.empty())
        {
                cout<< pqueInt.top() <<"出队"<<endl;
                pqueInt.pop();
        }
        return 0;
}


迭代器适配器:
1、流迭代器也是迭代器适配器,此外,还包括反向迭代器和插入迭代器。和使用流迭代器一样,使用反向和插入迭代器都必须包含头文件 #include<iterator>。
(1)反向迭代器
(2)插入迭代器适配器
#include <iostream>
#include <vector>
#include <iterator>
using namespace std;
int main()
{
        vector<int> vecInt = {1,2,3,4,5};
        vector<int>::iterator it=vecInt.begin();
        for(auto &elem:vecInt)
                cout<<elem<<" ";
        cout<<endl<<"-----------------------------------------"<<endl;

        ostream_iterator<int> osi (cout," ");    //创建输出流迭代器
        vector<int>::reverse_iterator rit = vecInt.rbegin();    //创建反向迭代器
        copy(rit,vecInt.rend(),osi);     //输出,容器中的内容拷贝到输出流迭代器中
//rit直接换成vecInt.rbegin()也可以
        cout<<endl;
        return 0;
}

#include <iostream>
#include <iterator>
#include <vector>
#include <list>
using namespace std;
template <typename Container>
void printElements(Container c)
{
        typename Container :: iterator it;
        for(it = c.begin();it != c.end(); ++it)
        {
                cout<<*it<<" ";
        }
        cout<<endl;
}
int main()
{
        vector<int> vecSrc = {1,2,3};
        list<int> listDest;
        copy(vecSrc.begin(),vecSrc.end(),back_insert_iterator<list<int> >(listDest));  
//尾插法,把vecSrc中的内容插入到listDest
        printElements(listDest);
        cout<<"--------------------------------"<<endl;
        list<int> listDest1;
        copy(vecSrc.begin(),vecSrc.end(),front_insert_iterator<list<int> >(listDest1));  
//头插法,把vecSrc中的内容插入到listDest1
        printElements(listDest1);
        cout<<"--------------------------------"<<endl;
        copy(vecSrc.begin(),vecSrc.end(),insert_iterator<list<int> >(listDest,++listDest.begin())); 
//指定位置插入法,把vecSrc中的内容,从listDest2的第二个位置开始插入
        printElements(listDest);
        return 0;
}


函数适配器:
函数适配器共有如下3种:
#include <functional>
1. 绑定器,有两个:
bind1st  (函数对象,指定值);    (过时)
将指定值绑定到函数对象的第1个参数上。
bind2nd  (函数对象,指定值);   (过时)
将指定值绑定到函数对象的第2个参数上。
bind  (函数对象,指定值… C++11)
绑定的参数的个数不受限制;对于不事先绑定的参数,需要传std::placeholders进去,从 _1 开始,依次递增(占位符)
2. 否定器,也有两个:
——not1()         //用于逆转一元断言
——not2()         //用于逆转二元断言
3. 成员函数适配器,也是两个:
——mem_fun()             //容器参数为类指针
——mem_fun_ref()        //容器参数为类对象
——mem_fn()       两者都能用(C++11)
绑定的参数的个数不受限制;对于不事先绑定的参数,需要传std::placeholders进去,从_1开始,依次递增

#include <iostream>
#include <functional>
using namespace std;
int func(int x,int y)
{
        return x+y;
}
class A
{
        public:
        A()
        {
                cout<<"A()"<<endl;
        }
        A(const A & rhs)
        {
                cout<<"A(const A&)"<<endl;
        }
        int func(int x,int y)
        {
                cout<<"A::func(int,int)"<<endl;
                cout<<"x="<<x<<endl;
                cout<<"y="<<y<<endl;
                return x+y;
        }
};
int main()
{
        auto f1=bind(func,10,placeholders::_1); 
 //绑定函数func,第一个参数为10,另外一个参数先不绑定,使用占位符
        cout<<f1(20)<<endl;     //占位符所在参数为20
        A a;
        auto f2=bind(&A::func,&a,placeholders::_1,placeholders::_2);
//这里A::func必须取地址,不然报错:这不是一个静态成员
//&a 和 a 的区别,一个不调拷贝构造函数,一个调构造函数
       // auto f2=bind(&A::func,placeholders::_1,placeholders::_2,placeholders::_3);
       // cout<<f2(a,1,2)<<endl;
        cout<<f2(1,2)<<endl;
        return 0;
}

#include <iostream>
#include <functional>
using namespace std;
using namespace std::placeholders;
void f(int n1,int n2,int n3,const int & n4,int & n5)
{
        cout<<"("<<n1<<","<<n2<<","<<n3<<","<<n4<<","<<n5<<")"<<endl;
}
struct Foo
{
        int data=10;    //C++11新特性
};
int main()
{
        int n=7,m=8;
        auto f1=bind(f,_2,_1,42,cref(n),ref(m));    //占位符数字表示第几个参数
        n=10;
        f1(1,2,1001,1002,1003);  
//2,1,42,10,8   实参调用时可以传递多余的参数,但是无效
        Foo foo;
        foo.data = 12;
        auto f3 = bind(&Foo::data,_1);     //还可以绑定数据成员
        cout<<f3(foo)<<endl;
        // auto f4 = bind(&Foo::data,foo);
        // cout<<f4(foo)<<endl;
        return 0;
}

#include<iostream>
#include<functional>
using namespace std;
using namespace std::placeholders;
struct foo
{
        void sum(int x,int y) {  cout<<x+y<<endl;  }
        int data = 10;
};
int main()
{
        foo fo;
        auto f1 = bind(&foo::sum,fo,_1,_2);
        f1(1,2);
        fo.data = 12;
        auto f2 = bind(&foo::data,&fo);  // &fo,不要写fo,这样效率不高
        cout<<f2(10)<<endl;  // 12
        auto f3 = bind(&foo::data,_1);   // 编译通过,但是不知道怎么用  f3(fo);
}
//3
//12

//函数适配器
//否定器,not1() 用于逆转一元断言
//not2() 用于逆转二元断言
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;
template<typename Container>
void print(Container& v)
{
        for(auto& elem:v)
                cout<<elem<<"  ";
        cout<<endl;
}
int main()
{
        int arr[] = {1,2,3,4,5,6,7};
        vector<int> v1(arr,arr+sizeof(arr)/sizeof(int));
        print(v1);
        less<vector<int>::value_type> it;
        vector<int> tmp(v1);
        replace_if(tmp.begin(),tmp.end(),bind1st(it,3),7);  // it为小于3,最终就是大于3的数据改成7
        print(tmp);
        tmp.clear();
        tmp = v1;
        replace_if(tmp.begin(),tmp.end(),not1(bind1st(it,3)),7);  // 否定器,小于3的改成7
        print(tmp);
        tmp.clear();
        tmp = v1;
        replace_if(tmp.begin(),tmp.end(),bind1st(not2(it),3),7);  // it被否定成大于3,所以最终就是小于3的数据被换成7
        print(tmp);
}
//成员函数适配器
#include<iostream>
#include<functional>
using namespace std;
using namespace std::placeholders;
struct foo
{
        void display_greeting(){  cout<<"hello,world!"<<endl;  }
        void display_num(int n){  cout<<n<<endl;  }
        int data = 7;
};
int main()
{
        foo fo;
        auto f1 = mem_fn(&foo::display_greeting);  // _1这个占位符可要可不要
        f1(fo);
        auto f2 = mem_fn(&foo::display_num);
        f2(fo,6);
        auto f3 = mem_fn(&foo::data);
        cout<<f3(fo)<<endl;
        return 0;
}

//成员函数适配器
//mem_fun()  //函数参数为类指针
#include<iostream>
#include<functional>
#include<algorithm>
#include<vector>
using namespace std;
class Num
{
        int _val;
        public:
        Num(){ _val=0; }
        Num(int val){ _val=val; }
        bool display(){ cout<<_val<<"  "; return true; }
        int squareval(){ _val*=_val; return _val; }
        int lessconst(int k){ _val-=k;return _val; }
        friend ostream& operator<<(ostream& os,const Num& rhs);
};
ostream& operator<<(ostream& os,const Num& rhs)
{
        os<<rhs._val;
}
int main()
{
        vector<Num*> v1;
        Num arr[10];
        for(int i=0;i<10;++i)
        {
                arr[i] = Num(i+1);
                v1.push_back(&arr[i]);
        }
        cout<<"原始数据:"<<endl;
        for_each(v1.begin(),v1.end(),mem_fun(&Num::display));
        //for_each(v1.begin(),v1.end(),mem_fun<bool,Num>(&Num::display));
// 两种写法都可以啊
        cout<<endl;
        // for_each(v1.begin(),v1.end(),mem_fun(&Num::squareval));
        for_each(v1.begin(),v1.end(),mem_fun<int,Num>(&Num::squareval));
        cout<<"数据平方:"<<endl;
        for(auto& elem:v1)
        cout<<*elem<<"  ";
        cout<<endl;
        for_each(v1.begin(),v1.end(),bind2nd(mem_fun<int,Num>(&Num::lessconst),5));
// bind2nd(函数对象,指定值) 把指定值绑定到函数对象的第二个参数上
        cout<<"减去常数:"<<endl;
        for(auto& elem:v1)
        cout<<*elem<<"  ";
        cout<<endl;
        return 0;
}
//成员函数适配器
//mem_fun_ref()   // 函数参数为类对象
#include<iostream>
#include<functional>
#include<algorithm>
#include<vector>
using namespace std;
class Num
{
        public:
                Num(){  val = 0;  }
                Num(int _val){  val = _val;  }
                bool display(){  cout<<val<<"  "; return true;  }
                bool isEven(){  return (bool)(val%2);  }
                bool isPrime()
                {
                        for(int i=2;i<(val/2);++i)
                                if(!(val%i)) return false;
                        return true;
                }
                friend ostream& operator<<(ostream& os,const Num& rhs);
        private:
                int val;
};
ostream& operator<<(ostream& os,const Num& rhs)
{
        os<<rhs.val;
}
int main()
{
        vector<Num> v1(12);  // 开辟12个空间
        //容器参数为类对象,Num
        for(int i=0;i<12;++i)
        {
                v1[i] = Num(i+1);
        }
        vector<Num>::iterator it;
        cout<<"原始数据:"<<endl;
        // for_each(v1.begin(),v1.end(),mem_fun_ref(&Num::display));
        for_each(v1.begin(),v1.end(),mem_fun_ref<bool,Num>(&Num::display));  // 这样写也可以
        cout<<endl;
        cout<<"删除质数:"<<endl;
        it = remove_if(v1.begin(),v1.end(),mem_fun_ref(&Num::isPrime));
        for(auto& elem:v1)
                cout<<elem<<"  ";
        cout<<endl;
        v1.erase(it,v1.end());
        for(auto& elem:v1)
                cout<<elem<<"  ";
        cout<<endl;
        vector<Num> v2(12);
        for(int i=0;i<12;++i)
        {
                v2[i] = Num(i+1);
        }
        v2.erase(remove_if(v2.begin(),v2.end(),mem_fun_ref(&Num::isEven)),v2.end());
        cout<<"删除基数:"<<endl;
        for(auto& elem:v2)
                cout<<elem<<"  ";
        cout<<endl;
        return 0;
}

适配器 STL的更多相关文章

  1. C++的STL

    今天,看一段代码的时候发现只一句话就做了个排序,是这样的: sort(rotateArray.begin(),rotateArray.end()); 很震惊,后来查了一下sort的用法, sort函数 ...

  2. STL学习系列七:优先级队列priority_queue容器

    1.简介 最大值优先级队列.最小值优先级队列 优先级队列适配器 STL priority_queue 用来开发一些特殊的应用,请对stl的类库,多做扩展性学习 这里给个例子: #include< ...

  3. c++ (P262—P277) STL

    STL的六大组件 容器(Container),是一种数据结构,如list,vector,和deques ,以模板类的方法提供.为了访问容器中的数据,可以使用由容器类输出的迭代器: 迭代器(Iterat ...

  4. STL总结之queue, priority_queue, stack

    之所以把这三个容器放在一起,是因为他们都是容器适配器.   STL中queue就是我们常用的FIFO队列,实现是一个容器适配器,这种数据结构在网络中经常使用.   queue的模板声明: templa ...

  5. C++ STL 一般总结

    以下内容来源网上 经过整合而成(转载) 一.一般介绍 STL(Standard Template Library),即标准模板库,是一个具有工业强度的,高效的C++程序库.它被容纳于C++标准程序库( ...

  6. C++顺序性容器、关联性容器与容器适配器

    什么是容器 首先,我们必须理解一下什么是容器,在C++ 中容器被定义为:在数据存储上,有一种对象类型,它可以持有其它对象或指向其它对像的指针,这种对象类型就叫做容器.很简单,容器就是保存其它对象的对象 ...

  7. STL之优先级队列priority_queue

    摘要: priority_queue,自适应容器(即容器适配器):不能由list来组建: 最大值优先级队列(最大值始终在对首,push进去时候) 最小值优先级队列: 优先级队列适配器 STL  pri ...

  8. STL之Queue(Q)

    STL的Queue(数据结构中的队列): 特点:FIFO 先进先出: 自适应容器(即容器适配器)   栈适配器STL queue  STL中实现的Queue: 用list来实现queue: queue ...

  9. C++之STL总结精华笔记

                       一.一般介绍      STL(StandardTemplate Library),即标准模板库,是一个具有工业强度的,高效的C++程序库.它被容纳于C++标准程 ...

随机推荐

  1. HTTP cookies 详解(国外一位大牛的文章)

    原文:http://blog.csdn.net/lijing198997/article/details/9378047 HTTP cookies,通常又称作"cookies",已 ...

  2. SQL Server批量数据导出导入BCP&Bulk使用

    数据导出导入,首先考虑使用什么技术实现导出与导入利用BCP结合Bulk技术实现数据的导出与导入 1.bcp数据导出(这里是命令行方式),导出的数据需是格式化的,有两种方式可选 a.对传输的数据格式要求 ...

  3. linux route命令的使用详解 添加永久静态路由 tracert traceroute

    linux route命令的使用详解 添加永久静态路由  tracert  traceroute route -n    Linuxroute  print  Windows traceroute  ...

  4. 005-线程sleep、join、yield、wait、notify、notifyAll、run、start、synchronized

    一.线程sleep join yield wait 1.sleep() 使当前线程(即调用该方法的线程)暂停执行一段时间,让其他线程有机会继续执行,但它并不释放对象锁.也就是说如果有synchroni ...

  5. python模块之signal信号

    简介 作用:发送和接收异步系统信号 信号是一个操作系统特性,它提供了一个途径可以通知程序发生了一个事件并异步处理这个事件.信号可以由系统本身生成,也可以从一个进程发送到另一个进程. 由于信号会中断程序 ...

  6. Checkpoint的运行原理和源码实现

    引言 Checkpoint 到底是什么和需要用 Checkpoint 解决什么问题: Spark 在生产环境下经常会面临 Transformation 的 RDD 非常多(例如一个Job 中包含1万个 ...

  7. hbase Java API 介绍及使用示例

    几个相关类与HBase数据模型之间的对应关系  java类 HBase数据模型 HBaseAdmin 数据库(DataBase) HBaseConfiguration HTable 表(Table) ...

  8. (转)在GitHub多个帐号上添加SSH公钥

    GitHub后台可以添加多个SSH Keys,但是同一个SSH Keys只能在添加在一个帐号上(添加时提示“Key is already in use”).理由很容易想到,SSH公钥使用时相当于用户名 ...

  9. Git 系列——第一步安装 Git

    之前也没有用过什么版本控制的工具,唯一用过的就是 SVN 了,不过也只是简单的使用而已,比如写好代码就签入,没了?是的,没了. 于是接触到了 Git 这个分布式版本控制软件,接下来就让我们好好学习,天 ...

  10. 004-notepad++安装。

    1.下载地址. 官网:https://notepad-plus-plus.org/ 2.安装.