C++容器学习笔记1——模版、迭代器

来源:互联网 发布:现任淘宝网总裁是谁 编辑:程序博客网 时间:2024/06/05 08:10

1模版

看书上说,所有的容器都是模版,于是我想先了解下模版是什么。

 一个模版可以说是创建一个类或者函数的蓝图。C++语言既有类模版也有函数模版,vector就是一个类模版。编译器根据模版创建类或者函数的过程称为实例化。当我们使用一个类类型的对象的时候,类定义必须是可用的,但是成员函数的定义不必出现,因此,我们将类定义和函数声明放在头文件中,而普通函数和类成员的定义放在了源文件中。模版则不同,为了生成一个实例化版本,编译器需要掌握函数模版或者类模版成员函数的定义。因此,与非模版代码不同,模版的头文件通常既包括声明也包括定义。

一、函数模版:


我们想定义一个函数compare,功能是比较大小,v1大就返回1,v2大返回-1,否则返回0;但是这里有个问题,就是你的参数类型不知道,那么这时你可以重载多个compare函数来完成,可是未免太麻烦,于是这里用到了函数模版。
template <typename T>int compare(const T &v1, const T &v2){    if(v1 < v2) return -1;    if(v2 < v1) return 1;    return 0;}

如上代码所示,模版关键字template,也可以用class代替,后面跟的是模版参数列表,里面如果有多个模版参数,用逗号分隔。
这里的模版参数会在我们使用模版的时候,指定模版实参,绑定到模版参数上。也就是说,使用到什么类型数据,T就会绑定成什么类型。
例如:

cout<<compare(1,0)<<endl;//这里就实例化出了int compare(const int&, const int&)

这种参数是类型参数,还有种非类型参数。
例如我们来比较两个字符串常量:

template<unsigned N, unsigned M>int compare(const char (&p1)[N], const char (&p2)[M]){    return strcmp(p1,p2);}

由于我们希望能比较不同长度的字符串常量,因此模版定义了两个非类型的参数,分别表示两个数组的长度。
实例化过程:

compare("hi","mom")//实例化为:int compare(const char (&p1)[3].const char (&p2)[4])//因为字符串末尾会有终结符所以+1

二、类模版


与函数模版不同,编译器不能为函数模版推断模版参数的类型,为了使用类模版,我们需要在尖括号内提供更多的信息。用户需要指出元素类型。
下面的代码是个例子,先了解这么多。

#include<stdio.h>#include<iostream.h>template<class T> class cao{    public:        cao()        {            x = 9;        }        void pp(T& z)        {            y = z;        }        void prr()        {            cout<<"y=="<<y<<endl;            cout<<"x=="<<x<<endl;        }    private:        int x;        T y;};int main(){    cao<int> cc;    int x = 55;    int &xx = x;    cc.pp(xx);    cc.prr();    return 0;}

2迭代器

能使用迭代器的不只是容器,string也可以使用,但是他不是容器。
有效迭代器指向某个元素或者容器尾元素的下个位置,其他情况均属失效。
能使用迭代器的类型都有能返回迭代器的成员,x.begin()和x.end()
begin是返回指向第一个元素的迭代器,end是返回指向尾元素下一个位置的迭代器,这样的迭代器没什么意义,只是个标记。当容器为空时,begin和end返回的是同一个迭代器。

下面是迭代器的一些用法:


*iter 返回迭代器iter所指元素的引用
iter->mem 解引用iter并获取该元素的名为mem的成员等价于(*iter).mem
可自加自减来表示位置前移后移。
用==和!=来判断迭代器是否指向同一个元素或者同一个容器的尾后迭代器。


一、拥有迭代器的标准库类型使用iterator和const_iterator

vector<int>::iterator it;       //it能读写verctor<int>中的元素string::iterator it;vector<int>::const_iterator it;     //it只能读取元素,不能写元素string::const_iterator it;

二、结合解引用和成员访问操作
看下面例子就明白了

vector<string>::iterator it;it->empty();

一个由string组成的vector对象,那么这种迭代器就可以使用string的成员函数了。(跟指针用法差不多)

三、 迭代器失效
任何insert和push操作可能导致迭代器失效,当编写程序时,程序必须确保迭代器在每次插入操作后更新。要避存储end操作返回的迭代器。待补充。。。。。。。。。。。。。。

ps:一个vector的对像vi,得到他中间位置的迭代器可以这么做

auto mid = vi.begin() + vi.size()/2//如果vi有20个元素,那么vi.size()/210
0 0