读书笔记:STL源码剖析之STL概论
STL六大部件:容器,算法,迭代器,仿函数,配接器,配置器
六大组件的交互关系: Container通过 Allocator取得数据储存空间, Algorithm通过 Iterator存取 Container内容, Functor可以协助 Algorithm完成不同的策略变化, Adapter可以修饰或套接 Functor.
STL发展:PH-》PJ-》RW-》SGI
常用STL头文件:vector.h deque.h list.h map.h algo.h function.h……
SGI头文件(STL真正实现于此):stl_vector.h stl_deque.h stl_list.h stl_map stl_function.h
STL标准头文件(无扩展名):algorithm deque functional hash_map hash_set iterator list map memory set stack
编译器组态设置:<stl_config.h>定义许多常量,标志某些组态的成立与否,以条件式写法,让预处理器根据各个常量决定取舍哪个程序段代码。
临时对象的产生与运用:
调用相应的constructor且不指定对象名称:int(8);常用于仿函数与算法的搭配
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
template<typename T>
class print
{
public:
//()重载
void operator()(const T& elem)
{
cout<<elem<<" ";
}
};
int main()
{
int ia[6]={0,1,2,3,4,5};
vector<int> iv(ia,ia+6);
//print<int>()是一个临时对象,不是一个函数调用操作
for_each(iv.begin(),iv.end(),print<int>());//()是已经重载过了。结果打印出:0 1 2 3 4 5
/*
for_each()事实上是個 function template,其实质如下 [effective STL item 41]
template<typename InputIterator, typename Function>
Function for_each(InputIterator beg, InputIterator end, Function f) {
while(beg != end)
f(*beg++);
}
*/
getchar();
return 0;
}
静态常量整数成员在class内部直接初始化
#include <iostream>
using namespace std;
template <typename T>
class testclass
{
public:// expedient
static const int _datai =5;
static const long _datal =3L;
static const char _datac ='c';
};
int main()
{
cout<<testclass<int>::_datai<< endl; //5
cout<<testclass<int>::_datal<< endl; //3
cout<<testclass<int>::_datac<< endl; //c
getchar();
return 0;
}
increment/decrement/dereference操作符
increment/dereference操作符在代器的实现上占有非常重要的地位,因为任何一个迭代器都必须实现出前进(increment, operator++)和取值(dereference operator*)功能,前者还分为前置式(prefix和后置式(postfix)两种,有非常规律的写法14.有些迭代器具备双向移动功能,那么就必须再提供 decrement操作
符(也分前置式和后置式两种)
#include <iostream>
using namespace std;
class INT
{
friend ostream& operator<<(ostream& os, const INT& i);
public:
INT (int i): m_i(i) {};
// prefix: increment and then fetch
INT& operator++()
{
++(this->m_i);//随着 class的不同,该行应该有不同的操作
return *this;
}
// postfix fetch and then increment
const INT operator++(int)
{
INT temp = *this;
++(*this);
return temp;
}
// prefix decrement and then fetch
INT& operator--()
{
--(this->m_i);//随着 class的不同,该行应该有不同的操作
return *this;
}
// postfix fetch and then decrement
const INT operator--(int)
{
INT temp = *this;
--(*this);
return temp;
}
// dereference
int& operator*() const
{
return (int&)m_i;
//以上转换操作告诉编译器,你确实要将 const int转为non- const Ivalue
//如果没有这样明白地转型,有些编译器会给你警告,有些更严格的编译器会视为错误
}
private:
int m_i;
};
ostream& operator<< (ostream& os, const INT& i)
{
os<<'['<<i.m_i<<']';
return os;
}
int main()
{
/*
[5]
[7]
[7]
[5]
5
*/
INT I(5);
cout<<I++<<endl;
cout<<++I<<endl;
cout<<I--<<endl;
cout<<--I<<endl;
cout<<*I<<endl;
system("pause");
return 0;
}
仿函数:
如果我们在一个类中重载了()运算符。那么这个类的对象就可以像调用函数一样去调用 。
仿函数在STL中的定义 #include
下面是一个将 operator()重载的例子:
#include <iostream>
using namespace std;
//由于将 operator()重载了,因此plus成了一个仿函数
template <class T>
struct plus
{
T operator() (const T& x, const T& y) const {return x+y;}
};
//由于 operator将()重载了,因此 minus成了一个仿函数
template <class T>
struct minus
{
T operator()(const T& x, const T& y) const {return x-y;}
};
int main()
{
//以下产生仿函数对象
plus<int> plusobj;
minus<int> minusobj;
//以下使用仿函数,就像使用一般函数一样
cout<< plusobj(3,5)<<endl;//8
cout<< minusobj(3,5)<<endl;//-2
//以下直接产生仿函数的临时对象(第一对小括号),并调用之(第二对小括号)
cout << plus<int>()(43, 50) << endl; //93
cout << minus<int>()(43, 50)<< endl; //-7
system("pause");
return 0;
}
来源:《STL源码分析》