迭代器,要为vector的double类型规范声明一个迭代器
vector
::iterator pd; vector
scores;//scores是一个vector
对象 pd = scores.begin();//初始地址 *pd = 22.3;//第一个元素的值 ++pd;
遍历整个容器的内容:
for(pd = scores.begin(); pd != scores.end(); pd++)
cout << *pd << endl;
push_back()是一个方便的方法,它将元素添加到矢量末尾,它负责内存管理,增加矢量的长度,使之能容纳新的成员
vector
scores;//创建一个空的向量 double temp; while(cin>>temp && temp >= 0) scores.push_back(temp); cout << "You entered" << scores.size() << " scores.\n";
erase()方法删除矢量中给定区间的元素,它接受两个迭代器参数,这些参数定义了要删除的区间,第一个迭代器指向区间的起始处,第二个迭代器位于区间终止处的后一个位置
scores.erase(scores.begin(), scores.begin() + 2);//即删除了begin()和begin()+1指向的元素
记住:区间[it1, it2]由迭代器it1和it2指定,其范围为it1到it2不包括it2
insert()方法与erase()相反,它接受3个迭代器参数,第一个参数指定了新元素的插入位置,第二个和第三个参数定义了被插入区间
old.insert(old.end(),new.begin()+1,new.end());//将矢量new中除第一个元素以外的所有元素插入到old矢量的第一个元素的前面
3)对矢量可执行的其他操作
搜索、排序、随机排序
for_each()函数用于许多容器类,它接受3个参数,前两个是定义容器中区间的迭代器,最后一个是指向函数的指针,被用来指向函数应用与容器区间中的各个元素,被指向的函数不能修改容器元素的值;可以用for_each循环代替for循环
vector
::iterator pr; for(pr = books.begin();pr != books.end(); pr++) ShowReview(*pr);
替换为
for_each(books.begin(),books.end(),ShowReview);//这样避免显式地使用迭代器变量
Random_shuffle()函数接受两个指定区间的迭代器参数,并且随机排列该区间中的元素
random_shuffle(books.begin(), books.end());//随机排列books矢量中的所有元素
sort()也要求容器支持随机访问
//版本一接受两个迭代器参数
vector
coolstuff; …… sort(coolstuff.begin(),coolstuff.end());//升序 //版本二如果容器元素是用户定义的对象,必须定义能够处理类型对象的operator<()函数 bool operator< (const Review & r1, const Review & r2) { if(r1.title < r2.title) return true; else if(r1.title == r2.title && r1.rating < r2.rating) return true; else return false; }
有了这样的函数之后,我们就可以对包含Review对象如books的矢量进行排序
sort(books.begin(), books.end());//升序排序,全排序
上述版本是按照title成员的字母顺序排序,如果title成员相同,则按照rating排序
bool WorseThan (const Review & r1, const Review & r2)
{
if(r1.title < r2.title)
return true;
else
return false;
}
有了这个函数,就可以将包含Review对象的books的矢量按rating升序排列
sort(books.begin(), books.end(), WorseThan);//升序排序,完全弱排序
4、通用编程技术
STL是一种通用编程技术,面向对象编程关注的是编程的数据方面,而通用编程技术关注的是算法,共同之处是抽象和创建可重用的代码。
通用编程技术旨在编写独立于数据类型的代码,在C++中,完成通用程序的工具是模板
1)模板使得算法独立于存储的数据类型,而迭代器使算法独立于使用的容器类型,它们都是STL通用方法的重要组成部分
2)为什么要使用迭代器?
目的是为了编写算法时,尽可能使用要求最低的迭代器,并让它适用于容器的最大区间。这样通过使用级别最低的输入迭代器,find()函数便可用于任何包含可读取值的容器,sort()函数由于需要随机访问迭代器,所以只能用于支持这种迭代器的容器。
//在一个double数组中搜索特定值的函数
double * find_ar(double * ar, int n, const double & val)
{
for(int i = 0; i < n; i++)
if(ar[i] == val)
return &ar[i];
return 0;
}
使用迭代器
typedef double * iterator;
iterator find_ar(iterator begin, iterator end, const double & val)
{
iterator ar;
for(ar = begin; ar != end; ar++)
if(*ar == val)
return ar;
return end;
}
总结下STL方法,首先是处理容器的算法,应尽可能用通用的术语来表达算法,使之独立于数据类型和容器类型,为使通用算法能够适用于具体情况,应定义能够满足算法需求的迭代器,并把要求加到容器设计上,所以要设计基本迭代器的特征和容器特征。
3)迭代类型
①输入迭代器――被程序用来读取容器中的信息
单向迭代器,只读,只能递增,不能倒退。
②输出迭代器――将信息从程序传输给容器的迭代器,程序的输出就是容器的输入
单向迭代器,只写
③正向迭代器――使用++操作符来遍历容器,正向迭代器既可以使得能够读取和修改数据,也可以使得只能读取数据
int * pirw;//读写迭代器
const int * pir;//只能读取迭代器
④双向迭代器――具有正向迭代器所有特性,同时支持两种递减操作符
reverse函数可以交换第一个元素和最后一个元素,将指向第一个元素的指针加1、将指向第二个元素的指针减去1,并且重复这种处理过程。
⑤随机访问迭代器――具有双向迭代器所有特性,同时添加了支持随机访问的操作
X表示随机迭代器类型,T表示被指向的类型,a和b是迭代器值,n为整数,r为随机迭代器变量或引用
随机访问迭代器操作:
a+n 指向a所指向元素后的第n个元素
a-n 指向a所指向元素前的第n个元素
a[] 等价于*(a+n)
4)概念、改进和模型
概念的具体实现被称为模型
①将指针用作迭代器
迭代器是广义的指针,指针满足所有迭代器的要求,迭代器是STL算法的接口,而指针是迭代器,所有STL算法可用于常规数组。
copy()、ostream_iterator和istream_iterator
copy() 将数据从一个容器复制到另一个容器中
int casts[10] = {6, 7, 2, 9, 4, 11, 8, 7, 10, 5};
vector
dice[10]; copy(casts, casts + 10, dice.begin());//前两项是复制的范围,后面是复制到什么位置
使用注意事项:
前两个参数最好是输入迭代器,最后一个参数最好是输出迭代器;
copy()函数将覆盖目标容器中已有的数据,我们不能将数据放入空矢量中;
ostream_iterator
是输出迭代器概念的一个模型,它是一个适配器(adapter