STL源码剖析:配接器
启
配接器就是适配器
STL中的适配器一共三种:
迭代器适配器
是一种观念上的改变,如将赋值操作变成插入,前进变成后退,等
函数适配器
STL中最广泛的配接器群体
可以实现连续配接
配接操作:bind,negate,compose
容器适配器
stack和queue的底层都是deque
Iterator adapter
iterator adapter中也维护一个容器,iterator adapter就是开放内部维护的容器的一些方法和关闭一些方法
back_insert_iterator:将赋值操作变成尾插
template <class Container>
class back_insert_iterator
{
protected:
Container* container; public:
explict back_insert_iterator(Container& x) : container(&x) {} // 主要提供的方法
back_insert_iterator<Container>& operator=(const typename Container::value_type& value)
{
container->push_back(value);
return *this;
} // 关闭下列方法
back_insert_iterator<Container>& operator*() { return *this; }
back_insert_iterator<Container>& operator++() { return *this; }
back_insert_iterator<Container>& operator++(int) { return *this; }
} template <class Container>
inline back_insert_iterator<Container> back_inserter(Container& x)
{
return back_insert_iterator<Container>(x);
}
- front_insert_iterator:将赋值操作变成头插
template <class Container>
class front_insert_iterator
{
protected:
Container* container; public:
explict front_insert_iterator(Container& x) : container(&x) {} // 主要提供的方法
front_insert_iterator<Container>& operator=(const typename Container::value_type& value)
{
container->push_front(value);
return *this;
} // 关闭下列方法
front_insert_iterator<Container>& operator*() { return *this; }
front_insert_iterator<Container>& operator++() { return *this; }
front_insert_iterator<Container>& operator++(int) { return *this; }
} template <class Container>
inline front_insert_iterator<Container> front_inserter(Container& x)
{
return front_insert_iterator<Container>(x);
}
- insert_iterator:将赋值操作变成在指定位置后插入,便于连续赋值
template <class Container>
class insert_iterator
{
protected:
Container* container;
typename Container::iterator iter; public:
explictinsert_iterator(Container& x, typename Container::iterator i) : container(&x), iter(i) {} // 主要提供的方法
insert_iterator<Container>& operator=(const typename Container::value_type& value)
{
container->insert(iter, value);
++iter;
return *this;
} // 关闭下列方法
insert_iterator<Container>& operator*() { return *this; }
insert_iterator<Container>& operator++() { return *this; }
insert_iterator<Container>& operator++(int) { return *this; }
} template <class Container, class Iterator>
inline insert_iterator<Container> front_inserter(Container& x, Iterator i)
{
typedef typename Container::iterator iter;
return insert_iterator<Container>(x, iter(i));
}
- reverse_iterator:将某个迭代器反向移动
template <class Iterator>
class reverse_iterator
{
protected:
Iterator current; public:
typedef Iterator iterator_type; // 正向迭代器
typedef reverse_iterator<Iterator> self; // 反向迭代器 reverse_iterator() {}
explicit reverse_iterator(iterator_type x) : current(x) {}
explicit reverse_iterator(const self& x) : current(x.current) {} iterator_type base() const { return currrent; } reference operator*() const
{
Iterator tmp = current;
return *--tmp;
} reference operator->() const
{
return &(operator*());
} self& operator++()
{
--current;
return *this;
} self& operator++(int)
{
self tmp = current;
--current;
return tmp;
} self& operator--()
{
++current;
return *this;
} self& operator--(int)
{
self tmp = current;
++current;
return tmp;
} self operato+(difference_type n) const
{
return self(current - n);
} self& operato+=(difference_type n)
{
current -= n;
return self;
} self operato-(difference_type n) const
{
return self(current + n);
} self& operato-=(difference_type n)
{
current += n;
return self;
} reference operator[](difference_type n) const
{
return *(*this + n)
}
}
- istream_iterator:绑定到istream上,拥有输入能力
template <class T, class Distance = ptrdiff_t>
class istream_iterator
{
protected:
istream* stream;
T value;
bool end_mark;
void read()
{
end_mark = (*stream) ? true :false;
if(end_mark)
{
*stream >> value;
}
end_mark = (*stream) ? true :false;
} public:
istream_iterator() : stream(&cin), end_mark(false) {}
istream_iterator(istream& s) : stream(&s), end_mark(false) { read(); } reference operator*() const { return value; }
reference operator->() const { return &(operator*()); } istream_iterator<T, Distance>& operator++()
{
read();
return *this;
} istream_iterator<T, Distance>& operator++(int)
{
istream_iterator<T, Distance> tmp = *this;
read();
return tmp;
}
}
- ostream_iterator:绑定到ostream上,拥有输出能力
template <class T>
class ostream_iterator
{
protected:
ostream* stream;
const char* string; // 每次输出后的间隔符 public:
ostream_iterator(ostream& s) :stream(&s), string() {}
ostream_iterator(ostream& s, const char* c): stream(&s), string(c) {} ostream_iterator<T>& operator=(const T& value)
{
*stream << value;
if(string)
{
*stream << string;
}
return *this;
} ostream_iterator<T>& operator*() { return *this; }
ostream_iterator<T>& operator++() { return *this; }
ostream_iterator<T>& operator++(int) { return *this; }
}
Function adapter
就是使用组合的方式,组合多个仿函数
对返回值进行逻辑取反:not1、not2
// 配接的仿函数接收两个参数
template <class Predicate>
class binary_negate : public binary_function<typename Predicate::first_argument_type, typename Predicate::second_argument_type, bool>
{
Predicate pre;
public:
explicate binary_negate(const Predicate& x) :prd(x) {} bool operator()(const typename Predicate::argument_type& x, typename Predicate::second_argument_type& y) const
{
return !(ped(x, y));
}
} template <class Predicate>
inline binary_negate<Predicate> not2(const Predicate& pred)
{
return binary_negate<Predicate>(pred);
}
- 对参数进行绑定:bind1st、bind2nd
就是指定仿函数中的参数中的某一个为固定值
template <class Operator>
class binder1st : public unary_function<typename Operator::second_argument_type, typename Operator::result_type>
{
Operator op;
typename Operator::first_argument_type value; public:
bind1st(const Operator& x, const typename Operator::first_argument_type* y) : op(x), value(y) {} typename Operator::result_type operator()(typename Operator::second_argument_type& x) const
{
return op(value, x);
}
} template <class Operator, class T>
inline binder1st<Operator> bind1st(const Operator& op, const T& x)
{
typedef typename Operator::first_argument_type arg1_type;
return binder1st<Operator>(op, arg1_type(x));
}
template <class Operator>
class binder2nd : public unary_function<typename Operator::first_argument_type, typename Operator::result_type>
{
Operator op;
typename Operator::second_argument_type value; public:
bind1st(const Operator& x, const typename Operator::second_argument_type* y) : op(x), value(y) {} typename Operator::result_type operator()(typename Operator::first_argument_type& x) const
{
return op(x, value);
}
} template <class Operator, class T>
inline binder2nd<Operator> bind1st(const Operator& op, const T& x)
{
typedef typename Operator::second_argument_type arg2_type;
return binder1st<Operator>(op, arg2_type(x));
}
- 对函数进行合成:compose1、compose2
// h(x) = f(g(x))
template <class Operation1, class Operation2>
class unary_compose : public unary_function<typename Operation2::argument_type,
typename Operation1::result_type>
{
Operation1 op1;
Operation2 op2;
public:
unary_compose(const Operation1& x, const Operation2& y) : op1(x), op2(y) {} typename Operation1::result_type operator()(typename Operation2::argument_type& x) const
{
return op1(op2(x));
}
} template <class Operation1, class Operation2>
inline unary_compose<Operation1, Operation2>compose1(const Operation1& x, const Operation2& y)
{
return unary_compose<Operation1, Operation2>(op1, op2);
}
// h(x) = f(g1(x), g2(x))
template <class Operation1, class Operation2, class Operation3>
class binay_compose : public unary_function<typename Operation2::argument_type,
typename Operation1::result_type>
{
Operation1 op1;
Operation2 op2;
Operation3 op3; public:
binay_compose(const Operation1& x, const Operation2& y, cosnt Operation3& z) : op1(x), op2(y), op3(z) {} typename Operation1::result_type operator()(typename Operation2::argument_type& x) const
{
return op1(op2(x), op3(x));
}
} template <class Operation1, class Operation2, class Operation3>
inline binay_compose<Operation1, Operation2, Operation3> compose2(const Operation1& x, const Operation2& y, cosnt Operation3& z)
{
return binay_compose<Operation1, Operation2, Operation3>(op1, op2, op3);
}
- 用于函数的指针:包装一般函数,使得一般函数也可以适用于Function adapter中
// 包装的函数只有一个参数
template <class Arg, class Result>
class pointer_to_unary_function : public unary_function<Arg, Result>
{
Result (*ptr)(Arg); public: explict pointer_to_unary_function(Result (*x)(Arg)) : ptr(x) {} Result operator()(Arg x) const
{
return ptr(x);
}
} template <class Arg, class Result>
inline pointer_to_unary_function<Arg, Result>ptr_fun(Result (*ptr)(Arg))
{
return pointer_to_unary_function<Arg, Result>(x);
}
// 包装的函数有两个参数
template <class Arg1, class Arg2, class Result>
class pointer_to_binary_function : public binary_function<Arg1, Arg2, Result>
{
Result (*ptr)(Arg1, Arg2); public: explict pointer_to_unary_function(Result (*x)(Arg1, Arg2)) : ptr(x) {} Result operator()(Arg1 x, Arg2 y) const
{
return ptr(x, y);
}
} template <class Arg1, class Arg2, class Result>
inline pointer_to_unary_function<Arg1, Arg2, Result>ptr_fun(Result (*ptr)(Arg1 x, Arg2 y))
{
return pointer_to_unary_function<Arg1, Arg2, Result>(x, y);
}
- 用于成员函数的指针:mem_fun、mem_fun_ref
mem_fun、mem_fun_ref修饰的成员函数不具备多态性质
// 无参数成员函数调用,其他有参数函数的调用方式类似
template <class S, class T>
class mem_fun_t : public unary_function<T*, S>
{
S (T::*f)();
public:
explict mem_fun_t(S (T::*pf)()) : f(pf) {} S operator()(T* p) const
{
return (p->*f)();
}
} template <class S, class T>
inline mem_fun_t<S, T> mem_fun(S (T::*f)())
{
return mem_fun_t<S, T>(f);
}
STL源码剖析:配接器的更多相关文章
- STL源码剖析 — 空间配置器(allocator)
前言 以STL的实现角度而言,第一个需要介绍的就是空间配置器,因为整个STL的操作对象都存放在容器之中. 你完全可以实现一个直接向硬件存取空间的allocator. 下面介绍的是SGI STL提供的配 ...
- STL源码剖析——空间配置器Allocator#2 一/二级空间配置器
上节学习了内存配置后的对象构造行为和内存释放前的对象析构行为,在这一节来学习内存的配置与释放. C++的内存配置基本操作是::operator new(),而释放基本操作是::operator del ...
- STL源码剖析:配置器
作用:对内存的管理 接口:申请和释放 内容: 几个全局函数 一级配置器 二级配置器 准备知识 POD是什么: Plain Old Data简称POD,表示传统的C语言类型:与POD类型对应的是非POD ...
- STL源码剖析(空间配置器)
前言 在STL中,容器的定义中都带一个模板参数,如vector template <class T, class Alloc = alloc> class vector {...} 其中第 ...
- STL源码剖析——空间配置器Allocator#3 自由链表与内存池
上节在学习第二级配置器时了解了第二级配置器通过内存池与自由链表来处理小区块内存的申请.但只是对其概念进行点到为止的认识,并未深入探究.这节就来学习一下自由链表的填充和内存池的内存分配机制. refil ...
- STL源码剖析——空间配置器Allocator#1 构造与析构
以STL的运用角度而言,空间配置器是最不需要介绍的东西,因为它扮演的是幕后的角色,隐藏在一切容器的背后默默工作.但以STL的实现角度而言,最应该首先介绍的就是空间配置器,因为这是这是容器展开一切运作的 ...
- 《STL源码剖析》相关面试题总结
原文链接:http://www.cnblogs.com/raichen/p/5817158.html 一.STL简介 STL提供六大组件,彼此可以组合套用: 容器容器就是各种数据结构,我就不多说,看看 ...
- 面试题总结(三)、《STL源码剖析》相关面试题总结
声明:本文主要探讨与STL实现相关的面试题,主要参考侯捷的<STL源码剖析>,每一个知识点讨论力求简洁,便于记忆,但讨论深度有限,如要深入研究可点击参考链接,希望对正在找工作的同学有点帮助 ...
- STL源码剖析之空间配置器
本文大致对STL中的空间配置器进行一个简单的讲解,由于只是一篇博客类型的文章,无法将源码表现到面面俱到,所以真正感兴趣的码农们可以从源码中或者<STL源码剖析>仔细了解一下. 1,为什么S ...
- STL"源码"剖析-重点知识总结
STL是C++重要的组件之一,大学时看过<STL源码剖析>这本书,这几天复习了一下,总结出以下LZ认为比较重要的知识点,内容有点略多 :) 1.STL概述 STL提供六大组件,彼此可以组合 ...
随机推荐
- 「从零单排canal 03」 canal源码分析大纲
在前面两篇中,我们从基本概念理解了canal是一个什么项目,能应用于什么场景,然后通过一个demo体验,有了基本的体感和认识. 从这一篇开始,我们将从源码入手,深入学习canal的实现方式.了解can ...
- Spring IoC BeanDefinition 的加载和注册
前言 本系列全部基于 Spring 5.2.2.BUILD-SNAPSHOT 版本.因为 Spring 整个体系太过于庞大,所以只会进行关键部分的源码解析. 本篇文章主要介绍 Spring IoC 容 ...
- 佛祖保佑,永无BUG d=====( ̄▽ ̄*)b
博主最近在网上看到了一个佛祖保佑永无BUG的帖子,各种符号画像层出不穷.也不知道是哪个人开的头,一堆人跟着转载. /** * 江城子 . 程序员之歌 * * 十年生死两茫茫,写程序,到天亮. * 千行 ...
- 手把手教你把web应用丢到服务器上(单页应用+ 服务端渲染)
前两篇文章中,我分别介绍了框架的搭建利用vue-cli + vant搭建一个移动端开发模板,并且把项目中axios请求和vuex的用法做了简要的介绍如何在项目里管理好axios请求与vuex.在这两篇 ...
- 使用scrapy实现去重,使用Redis实现增量爬取
面试场景: 要求对正在爬取的内容与mysql数据库中的数据进行比较去重 解决方式: 通过Redis来作为中间件,通过url来确保爬过的数据不会再爬,做到增量爬取. Redis数据库其实就是一个中间件, ...
- JS控制滚动条的位置
转载▼http://blog.sina.com.cn/s/blog_4481a3460100rwwu.html JS控制滚动条的位置:window.scrollTo(x,y); 竖向滚动条置顶 ...
- 错误记录——fail: Microsoft.AspNetCore.Server.Kestrel[13]
fail: Microsoft.AspNetCore.Server.Kestrel[13] Connection id "0HLPN4417RVEM", Request id &q ...
- C# 自定义常用代码段快捷键
不断更新中... 分享地址:http://pan.baidu.com/s/15oE0X
- Python3笔记012 - 3.3 条件表达式
第3章 流程控制语句 3.3 条件表达式 在程序开发中,经常会根据表达式的结果,有条件地进行赋值. # 返回两个数中较大的数 a = 10 b = 6 if a>b: r = a else: r ...
- HTML的<Object>标签怎么用?
<object>标签是一个HTML标签,用于在网页中显示音频,视频,图像,PDF和Flash等多媒体:它通常用于嵌入由浏览器插件处理的Flash页面元素,如Flash和Java项目.它还可 ...