STL的中心思想就是将容器和算法分开,分别独立设计和泛型化,然后通过迭代器来连接算法和容器。容器和算法利用C++ 中class template和function template机制来泛型化。设计STL的算法时,传递过来的参数往往是迭代器类型的参数,迭代器引用的容器数据类型当前是不确定的(template是在编译时确定数据类型的),当算法中需要利用迭代器所指对象的类型来定义或声明变量时,就会出现小小的困扰,因为C++中没有提供提取对象数据类型的操作(即使利用RTTI性质中的typied()来获取类型名,也不能用来做变量声明和定义之用)。这时我们就需利用function template的参数推导机制。下面举个简单例子来详细讨论一下:
//模板函数
template <class I>
void func(I iter){
...
}
这时想要在模板函数func里面定义一个迭代器引用的对象该怎么办?像我这样的初学者可能马上会想到容器中使用的方法,将该对象的类型也泛化,增加一个模板参数,即:
template <class I, class T>
void func(I iter){
T object;
...
}
可是这样可以吗?在容器的定义中如果要泛化类型,我们可以这样
template <class I, class T>
class Container{
...
T tObject;
I iObject;
typedef T* iter;
};
然后声明一个类型:
Container<int*, int> c;
而client在调用STL算法时并不需要了解容器的具体型别,因为它们是在容器声明时就已经设置好了,只需传入容器相应的迭代器。如果调用我们改进的func,编译时就会报错—— no matching function for call to 'func'。T类型是不确定的,因为T类型没有通过某种途径传递一个明确的类型过来。
如果这样像容器定义一样使用function template,我们调用
func<int*, int>(c.getIter()); //这样能行吗?确实可以编译通过,但感觉调用时不顺畅也很奇怪,也违背了STL设计的初衷。
那么该怎样解决这个问题呢?
其实STL中为迭代器指向对象的类型提供了专门技术——Traits编程技术,这里不作介绍,详见参考资料。template 参数推导机制只是简单的解决了部分 “迭代器所指对象的型别” 问题。利用参数推导机制,可以这样实现:
template <class I, class T>
void func_helper(I iter, T t){
T tmp;
... //这里做func原本该做的工作
}
template <class I>
void func(I iter){
func_helper(iter, *iter); //*iter作为附加参数
}
void caller(){
func(c.getIter());
}
可见func_helper中T的类型就是*iter类型,利用参数推导机制解决了上述问题。下面以插入排序为例,通过参数推导来解决实际问题,详细介绍下template function的实现。
插入排序的一般实现:
//普通版本
template<class T>
void insertSort(vector<T>& v){
int j;
for(int i = 1; i < v.size(); ++i)
{
T tmp = v[i];
for(j = i; j > 0 && tmp < v[j-1]; --j)
v[j] = v[j-1];
v[j] = tmp;
}
}
下面再按照STL算法的形式改写,STL sort的实现为带迭代器的双参数和附加函数子的三参数的两种形式。那么我们要:
(1)编写一个双参数和三参数的形式(为什么不能用一个带有默认参数值的三参数实例来实现呢?考虑一下),双参数实 际是三参数的一个特化,因此考虑用二参数函数调用三参数来实现。
(2)数组的访问由直接传入容器变为传入容器的迭代器;
(3)插入排序中tmp的类型和less<>仿函数的具体化要用到参数推导机制。
//STL版本
template<class I, class Cmp>
void insertSort(const I& begin, const I& end, Cmp lessThan);
template <class I, class T>
void _insertSort(const I& begin, const I& end, const T t);
template<class I, class T, class Cmp>
void _insertSort(const I& begin, const I& end, Cmp lessThan, const T& t);
template <class I>
void insertSort(const I& begin, const I& end){
if(begin != end)
_insertSort(begin, end, *begin); //这里要取begin所指向的值,避免越界,所以先判断
}
template <class I, class T>
void _insertSort(const I& begin, const I& end, const T t){
insertSort(begin, end, less<T>()); // 双参数调用三参数,less<T>中的类型也利用参数推导获取
}
template<class I, class Cmp>
void insertSort(const I& begin, const I& end, Cmp lessThan){
if(begin != end)
_insertSort(begin, end, lessThan, *begin);
}
//算法的具体实现
template<class I, class T, class Cmp>
void _insertSort(const I& begin, const I& end, Cmp lessThan, const T& t){
I j;
for(I i = begin+1; i != end; ++i){
T tmp = *i; //通过参数推导确定T类型
for(j = i; j != begin && lessThan(tmp, *(j-1)); --j)
*j = *(j-1);
*j = tmp;
}
}
上面就是个人对参数推导机制的粗浅理解,要深入了解迭代器指向对象的类型可参考《STL源码剖析》,以上代码来自于下面参考文献。代码都经过调试,可以正常运行。这里做一个学习过程的标记。
参考文献:
[1] 《STL源码剖析》
[2] 《数据结构与算法分析C++描述》
分享到:
相关推荐
STL之stack栈(csdn)————程序
一本很好的关于STL的讲解书。繁体字,从基础理论到实例用法,附有讲解源码。适合STL基础学习使用。
stl_function.h
一个成员取得下一个成员,从头到尾“走过”结构中的元素〔就象排序算法不关心元素是存 放在数组中或是线性表中)。Stepanov 研究过一些算法可以用一种抽象的方式实现,而且不 会影响效率。 1.2 STL 历史 1985 年,...
实现了选择排序、冒泡排序、二分查找、顺序查找、双向顺序查找
从根本上说,STL是一些“容器”的集合,这些“容器”有list,vector,set,map等,STL也是算法和其他一些组件的集合。这里的“容器”和算法的集合指的是世界上很多聪明人很多年的杰作。STL的目的是标准化组件,这样就...
经过对C学习,了解到其中很多对排序的算法,这里有:STL,选择,冒泡,快速,合并,插入,堆,计数等排序。 其中计数排序是线性排序,效率最高。
一 个报告,新手用 没什么用的 随便看看个报告,新手用 没什么用的 随便看看个报告,新手用 没什么用的 随便看看
STL中的排序算法一览
Introduction to STL, Standard Template Library 学习C++标准模板好材料
C++ STL中迭代器介绍 迭代器 迭代器提供对一个容器中的对象的访问方法,并且定义了容器中对象的范围。迭代器就如同一个指针。事实上,C++的指针也是一种迭代器。但是,迭代器不仅仅是指针,因此你不能认为他们一定...
本书是Ford和Topp两位教授于1996年出版的名著Data Structures with C++的第2版,新版中引入了在ANSI C 1998中正式规定的标准模板库(STL)来讲授数据结构,在全球范围内已经有数以万计的学生从中受益。 作者将C++...
STL中map用法详解 STL中map用法详解 STL中map用法详解
STL中的set和map都是自动排序的,但是如何修改其排序准则呢?本文档给出了修改思路和具体的实现代码。对于STL编程爱好者而言,实在是不可多得的好资料啊。
详细解说STL排序 详细解说STL排序 详细解说STL排序
STL对于C++编程者而言,相信都非常喜爱吧。但是其中的排序准则,你亲自试过修改吗?如何修改?请参考本文档的思路和实现过程吧。
Standard Template Library Programmer's Guide The Standard Template Library, or STL, ...STL是一个通用库,意味着它的组件被大量参数化:STL中的几乎每个组件都是模板。你应该确保你了解模板在C++之前你使用STL。
详细解说 STL 排序,可以下载看看。了解多点stl排序问题
STL 是“Standard Template Library”的缩写,中文译为“标准模板库”。STL 是 C++ 标准库的一部分,不用单独安装。 C++ 对模板(Template)支持得很好,STL 就是借助模板把常用的数据结构及其算法都实现了一遍,...
文字加代码示例,最全的剖析,适合STL初学者,入门级别的