分类: C/C++
2015-04-08 11:25:12
1、容器(Containers):各种数据结构,如Vector,List,Deque,Set,Map,用来存放数据,STL容器是一种Class Template,就体积而言,这一部分很像冰山载海面的比率。
2、算法(Algorithms):各种常用算法如Sort,Search,Copy,Erase,从实现的角度来看,STL算法是一种Function Templates。
3、迭代器(Iterators):扮演容器与算法之间的胶合剂,是所谓的“泛型指针”,共有五种类型,以及其它衍生变化,从实现的角度来看,迭代器是一种将:Operators*,Operator->,Operator++,Operator--等相关操作予以重载的Class Template。所有STL容器都附带有自己专属的迭代器——是的,只有容器设计者才知道如何遍历自己的元素,原生指针(Native pointer)也是一种迭代器。
4、仿函数(Functors): 行为类似函数,可作为算法的某种策略(Policy),从实现的角度来看,仿函数是一种重载了Operator()的Class 或 Class Template。一般函数指针可视为狭义的仿函数。
5、配接器(适配器)(Adapters):一种用来修饰容器(Containers)或仿函数(Functors)或迭代器(Iterators)接口的东西,例如:STL提供的Queue和Stack,虽然看似容器,其实只能算是一种容器配接器,因为 它们的底部完全借助Deque,所有操作有底层的Deque供应。改变Functor接口者,称为Function Adapter;改变Container接口者,称为Container Adapter;改变Iterator接口者,称为Iterator Adapter。配接器的实现技术很难一言蔽之,必须逐一分析。
6、分配器(Allocators):负责空间配置与管理,从实现的角度来看,配置器是一个实现了动态空间配置、空间管理、空间释放的Class Template。
——《STL源码剖析》
函数子类(函数对象)的由来:
在STL里,我们经常需要对容器内元素进行批量操作,手写循环确实是个方法,但是,代码冗余,而且效率普遍偏低,这就需要一个批量操作方法,能够对容器内的元素进行批量操作,那么,怎么操作,操作什么,这就需要用户去定义了,你需要告诉程序,你想要什么样的操作,一般人对于这种问题的第一反应就是函数指针,确实,通过传递一个函数指针可以让程序执行特定的操作,这也确实是一个方法,但是按CPP Primer Plus上的原文来说,它有一个很大的弊端,那就是函数指针是必须指定参数以及返回类型的,而STL属于泛型编程,加入用函数指针来操作的话,是违反泛型思想的本质的,因此,这就需要一个能取代函数指针的东西了,而这个东西就是所谓的函数对象。
判别式类是指函数子类,它的operator()函数是一个判别式,也就是说,它的operator()返回true 或false .
例子:effective 41条
template
class MeetsThreshold:public std::unary_function
private:
const T threshold ;
public:
MeetsThreshold(const T& threshold);
bool operator()(const Widget&) const ;
};
struct WidgetNameCompare:public std::binary_function
bool operator()(const Widget& lhs,const Widget& rhs) const;
};
注意operator()的类型是const Widget& 但是给unary_function binary_function 的类型是Widget . 一般情况下传递给unary_function binary_function非指针类型要去掉const 和 引用。如果operator() 参数是指针类型,情况就不一样了, 二者要一样。如下
struct WidgetNameCompare:public std::binary_function<const Widget*,const Widget*,bool>{
bool operator()(const Widget* lhs,const Widget* rhs) const;
};
这样就完成了可配接函数对象
list
list
list
引入函数子类概念,如上所述,STL 泛型思想就统一了,不必非得引入函数指针而违背泛型原则,这样的STL就正统了。
STL 函数子类: less
为了更好理解上面,关于函数子类原理可以查资料了解一下。思想就是类可以保存本类指针成员(非静态),并且重载了operator(),从而随时可以用指针去调用operator();
函数子类是值传递和返回,参见effective 38 条
函数子类判别式应是“纯函数” 参见effective 39 条
ptr_fun men_fun men_fun_ref 的由来
先说函数对象配接器mem_fun mem_fun_ref :
class TestClass1{
public:
TestClass1(int d):data(d)
{}
bool test() const
{
return data>4;
}
private:
int data;
};
TestClass1 *t1 = new TestClass1(1);
TestClass1 *t2 = new TestClass1(2);
TestClass1 *t3 = new TestClass1(4);
TestClass1 *t4 = new TestClass1(5);
std::vector
lpt.push_back(t1);
lpt.push_back(t2);
lpt.push_back(t3);
lpt.push_back(t4);
std::vector
class TestClass1{
public:
TestClass1(int d):data(d)
{}
bool test(int val) const
{
return data>val;
}
private:
int data;
};
std::vector