Essential C++笔记[Chapter 3泛型编程风格] 上:


Standard Template Library(STL) 主要由两部分组成:一是 容器(container),包括vector、list、set、map等类;另一部分是用以操作这些容器的 泛型算法(generic algorithm),包括find()、sort()、replace()、merge()等。
顺序性容器(sequential container): vector、list deque
关联性容器(associative container): map set
泛型算法 通过 function template技术,达到“与操作对象的类型相互独立”。实现的关键在于,不直接在容器上操作,而是借由一对Iterator(first,last)标示要迭代的元素范围。

3.1 指针的算术运算

任务:给定一个储存int的vector,和一个整数值。如果vector中存在该值则返回一个指针指向vector中的该值的位置;否则返回0,标示该值不在vector中。

int* find(const vector<int> &vec, int value) 
{
	for ( int i = 0; i < vec.size(); i++ ){
		if ( value == vec[i] )
			return &vec[i]
	}
	return 0;
}

测试这个函数确实可以满足需求,如果要让其不仅可以处理int,更可以处理任何类型(该类型定义有equality运算符)。
只要我们将find()函数以function template呈现即可。

template <typename elemType>
elemType* find(const vector<elemType> &vec, elemType value) 
{
	for ( int i = 0; i < vec.size(); i++ ){
		if ( value == vec[i] )
			return &vec[i]
	}
	return 0;
}

新需求:让这个函数可以同时处理vector和array内的任意类型元素。
一个方法使用函数重载(overload)一份处理vector一份处理array。这不是本章节的重点所以不考虑这个方法。
面对难题我们可以 将该问题分解成数个较小、相对简单的问题。
我们可以将这个大问题分解成:(1)将array的元素传入,但是不指明array类型。(2)将vector的元素传入,但是不指明vector类型。
问题一解决方案:将array指针传入并且传入一个参数告知在何处停止读取;
解法一:增加一个参数表示数组的大小

template < typename elemType>
const elemType* find(const elemType *array, int size,
				const elemType &value)
{
	if ( !array || size < 1)
		return 0;
	for ( int i = 0; i < size; i++)
		if ( array[i] == value )
			return &array[i];
	return 0;
}

解法二:传入另一个地址,指示array读取操作的终点。

template < typename elemType>
//first 表示数组第一个元素位置,last表示最后一个元素的下一地址;
const elemType* find(const elemType *first, const elelmType *last,
				const elemType &value);
{
	if ( !first || first == last)
		return 0;
	for ( ; first != last; first++)
		if ( *first == value )
			return first;
	return 0;
}

传入last是合法的,但是对其进行读取或者写入都是不合法的。

问题二解法:
分析:问题二是说不论vector的元素类型是什么,都能依次访问其中的元素。array和vector都是以一块连续内存储存元素,所以我们可以使用和array一样的处理方式,将一组用来表示“起始地址/结束地址”的参数传入find()。但是vector可以是空的,array则不然。我们需要做的是获取vector的起始地址和结束地址然后传入上面的程序即可。

// 获取vector的起始地址
template <typename elemType>
inline const elemType* vbegin(const vector<elemType> &vec)
{
    return vec.empty() ? 0 : &vec[0];
}
// 获取vector的结束地址
template <typename elemType>
inline const elemType* vend( const vector<elemType> &vec)
{
    return vec.empty() ? 0 : &vec[vec.size()-1];
}

这样实现了find() ,只需这一份就同时处理vector和array。
如果还想扩展find()的功能,令其也能支持list类别。解决方案是:在底层指针的行为之上提供一层抽象,取代程序原本的“指针直接操作”。将底层指针的处理全都放在这个抽象层中,让用户不用直接面对指针操作。

3.2 了解Iterator(泛型指针)

Iterator(泛型指针)即上节中提到的取代“指针操作”的抽象层。通过C++的类机制实现。并提供了dereference(*)、inequality(!=)、increment(++)运算符。

3.3 所有容器的共通操作

3.4 使用顺序性容器

3.5 使用泛型算法

3.6 如何设计一个泛型算法

3.7 使用Map

3.8 使用Set

3.9 如何使用Iterator Inserter

3.10 使用iostream Iterator

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值