本帖最后由 行客 于 2019-2-18 17:21 编辑
你在学习STL是吗?
首先你必须清楚为什么会出现迭代器。
“指针”对全部C/C++的程序员来说,一点都不陌生。
在接触到C语言中的malloc函数和C++中的new函数后。我们也知道这两个函数返回的都是一个指针。该指针指向我们所申请的一个“堆”。提到“堆”。就不得不想到“栈”。从C/C++程序设计的角度思考,“堆”和“栈”最大的差别是“栈”由系统自己主动分配而且自己主动回收,而“堆”则是由程序员手动申请。而且显示释放。假设程序员不显示释放“堆”,便会造成内存泄漏。内存泄漏的危害大家知道,严重时会导致系统崩溃。
既然“指针”的使用者一不小心就可能导致内存泄漏,那么我们怎样可以使得指针的使用变得更安全呢?从C++面向对象的角度分析,我们有没有可能将“指针”封装起来,使得用户不直接接触指针,而使用一个封装后的对象来替代指针的操作呢?
答案是显然的,“智能指针”(smart pointer)正解决这类问题,尤其是在防止内存泄漏方面做得很突出。
C++标准库std中提供了一种“智能指针类”名为"auto_ptr",先看以下的代码:void f()
{
int *p=new int(42);
////////此处发生异常////
delete p;
}
正如上面的代码所看到的。假设在两条语句中间发生异常,会导致指针p所指的那块内存泄漏。由于在执行delete之前发生异常,就不会自己主动释放堆。然而。假设使用auto_ptr对象取代常规指针,将会自己主动释放内存,由于编译器可以保证提前执行其析构函数。这样,我们就行将上述代码改为:
#include<memory>//auto_ptr的头文件
void f()
{
auto_ptr<int>p(new int (42));
}
通过以上的分析。我们便对智能指针有了一定的了解:
迭代器iterator就是一种智能指针。它对原始指针进行了封装,而且提供一些等价于原始指针的操作,做到既方便又安全。
一提到STL,必需要立即想到其基本的6个组成部件,各自是:容器、算法、迭代器、仿函数、适配器和空间分配器。
迭代器是连接容器和算法的一种重要桥梁。
为什么这样说呢?我们举个样例来说明原因。#include<iostream>
#include<algorithm>//用到find函数
#include<vector>
using namespace std;
int main()
{
vector<int>vec;
int i;
for(i=0;i<10;i++)
{
vec.push_back(i);
}
if(vec.end()!=find(vec.begin(),vec.end(),7))
{
cout<<"find!"<<endl;
}
else
{
cout<<"not find!"<<endl;
}
system("pause");
return 0;
}
上述代码中。值得注意的是用到的find函数,find函数的函数原型为:template<class _InIt,class _Ty> _InIt find(_InIt _First, _InIt _last, const _Ty & _val),从find函数原型能够看出find函数是一个函数模板,函数的形參中前两个參数为_InIt。该參数是InputIterator的缩写。最后一个參数则是一个随意类型变量的引用。而我们的程序在使用find函数实。传入的实參为find(vec.begin(),vec.end(),7)。这样我们的形參迭代器就将算法find和容器vector联系起来了,从这个角度我们能够非常easy理解为什么说迭代器是算法和容器的联系的桥梁了。
所以:STL中,算法不直接操作容器,是间接通过迭代器来进行处理的。也就是,算法最终的操作结果是受迭代器的操作情况而确定的。因此,“标准库算法对迭代器而不是容器进行操作。因此算法不能(直接)添加或删除元素”。
但是,并非就完全不能实现添加或删除容器元素。只要迭代器的具体操作中实现了容器的添加或删除,就达到了算法操作的目的。
其实这里的Note本意是为了解释为什么容器还剩下10个元素,为什么“此位置之后的元素仍然存在”。
如有不明白的地方,请继续跟帖。 |