博文参考书籍为essential C++,是该书的读书笔记。
假如我们有如下一个问题:
对于一个存储整数的vector以及某一个整数值,我们需要判断该整数值是否与vector内某一个整数值相等,
若存在,则返回一个指针指向该值,若不在,返回0。
我们可以很快的完成一个简单的程序。
以下是完成该方法的一段程序:
#include
#include
using namespace std;
const int* find1(const vector &vec, int value)
{
for (int ix = 0; ix < vec.size(); ++ix)
if (vec[ix] == value)
return &vec[ix];
return 0;
}
int main(int argc, char** argv)
{
int input;
vector number;
for (int i = 0; i < 10; i++)
number.push_back(i);
cout << "please put input\n";
cin >> input;
if (find1(number, input))
cout << "find "<< *find1(number, input);
system("pause");
}
在上面的程序中,我们设计了一个返回指针的函数,该指针指向的类型是一个int类型(使用的是const int*类型,因为输入是该类型的一个引用,主要是为了防止函数在使用该vector的引用时去修改vector,所以输入为只读的形式),若是我们要求不仅可以判断整数,而是可以判断任何类型的vector,那我们该如何设计函数呢,以下就是一个命名为find2的function template,能够实现针对不同类型的vector,来判断其中是否有相应的某个value相等的元素,当然,前提是该数据类型中有相等的运算。
template
const elemType* find2(const vector &vec,//修改后版本,针对不同类型的vector都可以返回
const elemType &value)
{
for (int ix = 0; ix < vec.size(); ++ix)
if (vec[ix] == value)
return &vec[ix];
return 0;
}
在程序运行结果中,对于整数vector于第一个函数的效果一样。对其他类型的vector也有一样的效果。
如下:
int main(int argc, char** argv)
{
string input_s;
string namelist[4] = { "mike", "jack", "frank", "jone" };
vector name(namelist,namelist+4);
cout << "please input name\n";
cin >> input_s;
if (find2(name, input_s))
cout << "find "<< *find2(name, input_s);
system("pause");
}
对于find2函数来说,它能处理不同类型的vector,但是要是输入函数的是一个array,便不能处理,难道我们需要写一个重载函数吗?所以我们期望能写出能同时处理vector和array的函数,那么这个函数该怎么写呢?
假设我们有一个数组,我们需要寻找该数组中是否有与某个值相等的元素,我们将该数组传入某个函数中,这里的传入数据,我们一般推荐对于较大数据进行传址而非传值,并且如果我们在该函数中对于该变量并不希望进行修改,推荐的方式是在之前加上const,这是一个好习惯。对于这样的函数来说,其输入变量是一个数组,但是却未对数组的长度有要求,所以我们需要在传入地址的同时明确知道该数组的范围,所以一般有以下两种方法:
一、给这个函数数组第一个元素的地址,并告诉它这个数组有多大,其实现的函数如下:
template
const elemType* find3(const elemType* array,int size,const elemType &value)
{
if (!array || size < 1)
return 0;
for (int ix = 0; ix < size; ++ix)
if (array[ix] == value)
return &array[ix];
return 0;
}
在该函数中,我们将数组的一个元素的地址和该数组的长度传入,并对数组中所有的元素进行比较,该函数对于数组中所存储的元素的类型并没有要,能够处理所有的数组。在上面的程序最后,我们对数组中的元素是使用下标的方式,我们同样可以写成如下的形式,直接做指针的算术,两者是一样的:
template
const elemType* find3(const elemType* array,int size,const elemType &value)
{
if (!array || size < 1)
return 0;
for (int ix = 0; ix < size; ++ix,++array)
if (*array == value)
return array;
return 0;
}
二、第二种方法就是给函数传入两个指针,数组的第一个元素的地址和最后一个元素的下一个地址,这种方式只需传入两个指针,不必在函数中带有array的声明。其函数如下:
template
const elemType* find4(const elemType* first, const elemType* last, const elemType& value)
{
if (!first || !last)
return 0;
for (;first!=last; ++first)
if (*first == value)
return first;
return 0;
}
以上部分程序中,我们完成了对数组的find功能,但是对于vector呢,因为vector和array一样是顺序存储的结构,所以我们同样可以使用上面的find4函数,但是我们需要知道,vector可以是空的,所以我们需要对其进行判断是否为空,这个判断我们不必加在调用find函数前,我们一般有取第一个元素地址的函数:
template
inline elemType* begin(const vector &vec)
{return vec.empty()?0:&vec[0];}
若是空的vector直接返回为0,0作为find的输入也会返回0,同样end函数也是类似的。所以我们完成了这个find函数,使其能够同时处理不同类型的vector和array,完成了我们的目的。但是若输入的容器类型的存储空间不是连续的,那么我们便不能通过指针的算术来进行确定了,对于list的容器,我们又该怎么办呢?有什么方法能够同时处理连续性存储的容器和非连续性存储容器甚至所有的容器类呢?这样的函数又该怎么写呢?我们将继续深入学习相关的内容。