美文网首页
标准模板STL-vector

标准模板STL-vector

作者: gpfworld | 来源:发表于2018-12-31 10:21 被阅读0次
    3. vector容器
    
        (1)普通数组与vector
    
        只要能够使用数组的地方,就一定可以使用vector代替,前面说到,vector其实就是
        数组,只是空间开辟于堆中。普通数组长度是固定的,但是vector容器的容量和大小
        可以根据实际情况不同而改变。
    
        容量与大小:
        对于vector来说容量和大小是不同的,容量>=大小,
        容量:vector容器最大能够存放的元素个数。
        大小:vector容器当前实际存放的元素个数。
        
        使用数组存放数据时实际上也存在容量与大小的关系,只是平时我们不并
        不关心这个问题。
    
        当数组空间未存满时,数组实际元素个数就是大小,数组的最大元素空间
        就是容量。
    
        获取vector的容量和大小:
        分别通过vector的size()和capacity()成员函数便可以获取vector的容
        量和大小。
    
        (2)vector容器的优缺点
        优点:vector容器的容量和大小可以可根据情况变更。
        缺点:vector本质上是一个单端数组,在其末尾添加和删除元素,效率都很高,
            但是在vector的中间插入和删除效率就很低,这会导致大量的元素需
        要被移动。
        
        (3)创建vector
        (1)创建一个空的,存放基本类型数据的vector
        std::vector<int> v;
        
        vector属于std命名空间,因此需要使用std::,该定义表示利用vector
        容器类的默认构造器创建了一个vector,该容器存放的数据类型为int型,
        vector的容量和大小都是0。
        
        cout <<"大小:"<< v.capacity() <<endl;
        cout <<"容量:"<< v.size() <<endl;
        打印结果都为0。
        
        创建一个空的vector容器并不是一种高效的创建方式,因为向vector
        容器添加新元素时,会导致频繁的扩充容器空间,操作效率很低,因此
        很多时候我们都会给容器预先指定一定大小的初始空间,提高操作效率。
        
    
        (2)创建一个有一定大小vector
    
       (1)创建存放基本类型数据的vector
        std::vector<int> v(10);
        
        调用vector容器的有参构造函数,该参数用于说明容器的大小和容量。
    
        创建有一定空间,用于存放基本类型数据的vector时,
        (1)所有元素都会被初始化为0
        (2)最开始时,容器的容量==大小,
    
        比如打印出定义的v的容量和大小,
        cout <<"容量:"<< v.capacity() <<endl;
        cout <<"大小:" v.size() <<endl;
        打印结果都为10。
        
        当向容器里面插入新的数据时,容器中的容量扩大的速度大于大小扩大的速度,
        多出来的冗余空间是为了提高容器的效率。
        比如:
          v.insert(v.begin(), 23);
        
            cout <<"容量:" v.capacity() << endl;
        cout <<"大小:" v.size() << endl;
    
        打印结果:
          容量:20
          大小:11
    
    
       (2)创建存放类类型对象的vector  
    
        student() {
        public:
        private:
            string anme;
            int num;
        };
        std::vector<Student> vstus(20);
        
        创建一个vector容器,包含20个Student对象,每个对象都调用Student
        类的默认构造函数进行初始化,所以对于Student类来说,要求必须实现
        其默认构造函数。
        
        由于这里定义的Student类没有其它构造函数,所以编译器会提供默认
        构造函数。
    
        至于需不需要显式定义拷贝构造函数和析构函数,需要根据实际情况而
        定,为了保证类定义标准化和完整性,建议写出。
        
        在类中最好提供=和<的重写,否则当涉及给最容器中的内容进行排序时,
        可能会出现问题。不过很多时候,容器都提供了默认的比较方法,因此
        都能按照默认比较方法对容器中的数据进行排序。
        
        
    (3)创建时给容器给一些初始值
        不能够直接使用一组数据初始化vetor容器,但是可以使用定义好的c++
        数组初始化vector容器。
    
        (1)方法1:赋值
            (1)基本类型数据
                int buf[] = {1, 2, 4, 3, 6, 7, 8, 9, 0}; 
                    std::vector<int> v(10);
    
                    for(int i=0; i<sizeof(buf)/sizeof(buf[0]); i++) {
                            v[i] = buf[i];
                    }   
    
                    for(int i=0; i<v.size(); i++) {
                            cout << v[i] << endl;
                    }   
    
            (2)类对象
                #include <iostream>
                #include <stdio.h>
                #include <vector>
    
                using namespace std;
                /* 定义一个学生结构体 */
                class Student {
                public:
                        Student(const string name=" "):name(name) { }
                        string name;
                };
    
                int main(void)
                {    
                        /* 定义一个对象数组并初始化对象数组 */
                        Student stu[10];
                        char tmp[3] = {0};
                        string n("name");
                        for(int i=0; i<sizeof(stu)/sizeof(stu[0]); i++) {
                                sprintf(tmp, "%d", i);
                                stu[i] = Student(n+tmp);
                        }
    
                        /* 使用赋值的方式,对象数组元素赋值给vector容器 */
                        std::vector<Student> v(10);
                        for(int i=0; i<sizeof(stu)/sizeof(stu[0]); i++) {
                                v[i] = stu[i];
                        }
    
                        for(int i=0; i<v.size(); i++) {
                                cout << v[i].name << endl;
                        }
    
                        return 0;
                }   
                
        (2)方法2
            (1)基本类型
                int buf[] = {1, 2, 4, 3, 6, 7, 8, 9, 0}; 
                    std::vector<int> v(buf, buf+sizeof(buf)/sizeof(buf[0]));
    
                    for(int i=0; i<v.size(); i++) {
                            cout << v[i] << endl;
                    }  
                或者
                std::vector<int> v(10, 3.14);
    
                    for(int i=0; i<v.size(); i++) {
                            cout << v[i] << endl;
                    }
                创建一个10个元素空间的vector容器,初始值都是3.14。
            (2)类对象
                #include <iostream>
                #include <stdio.h>
                #include <vector>
    
                using namespace std;
    
                /* 定义一个学生结构体 */
                class Student {
                public:
                        Student(const string name=" "):name(name) { }
                        string name;
                }; 
                
                int main(void)
                {    
                        /* 定义一个对象数组并初始化对象数组 */
                        Student stu[10];
                        char tmp[3] = {0};
                        string n("name");
                        for(int i=0; i<sizeof(stu)/sizeof(stu[0]); i++) {
                                sprintf(tmp, "%d", i); 
                                stu[i] = Student(n+tmp);
                    }
    
                    /* 利用对象数组初始化vector容器 */
                    std::vector<Student> v(stu, stu+sizeof(stu)/sizeof(stu[0]));
    
                    for(int i=0; i<v.size(); i++) {
                            cout << v[i].name << endl;
                    }
    
                    return 0;
            }
            
            从例子中不难看出,构造函数需要两个迭代器参数用于指定间隔,
            这里使用的是指针,前面讲过,指针其实就是一种特殊的迭代器,
    
            这两个参数指定的是半开间隔,所谓半开间隔(半开区间)就是
            包含前一个范围界限,但是不包含后一个范围界限。 
                
    (4)resize()函数和reserve()函数
        (1)resize()函数
            利用参数指定新的元素个数,用于修改容器的大小(不是容量),
            如果新的大小比原来小,尾部元素就被删除。如果比原来大小
            要大,就在容器尾部添加新元素空间,如果数据是基本类型,
            新加的元素的默认值为0,如果对象的话,需要看实际情况。
                    std::vector<int> v(10);
    
                    cout << v.size() << endl;
                    v.resize(6);
                    cout << v.size() << endl;
    
            
        (2)reserves()函数
            利用其参数用于指定vector容器的最小容量,如果设置的容量
            值小于当前容量,容量就保持不变。        
                    std::vector<int> v(10);
    
                    cout << v.capacity() << endl;
                    v.reserve(16);
                    cout << v.capacity() << endl;
    
            
    (5)在容器中存放指针
    
        在前面的内容提到过,可以在容器中存放副本和指针,存放副本方式的
        效率比较低,修改了副本后,原对象的值不会变化,修改了原对象的值
        后,容器中存放的副本的值又不会发生变化。
            
        存放指针可以提高效率,但是要注意,如果容器存放的指针指向的空间
        释放了的话会造成野指针,因此使用时需要格外小心。
        
        (1)例子:存放副本的
            #include <iostream>
            #include <stdio.h>
            #include <vector>
    
            using namespace std;
            /* 定义一个学生结构体 */
            class Student {
            public:
                    Student(const string name=" "):name(name) { }
                    string name;
            };
    
    
            int main(void)
            {    
                    Student stu[5];
                    std::vector<Student> v(5);
    
                    for(int i=0; i<5; i++) {
                            stu[i] = Student("name");
                            v[i] = stu[i];
                    }
    
                    for(int i=0; i<5; i++) cout << v[i].name <<endl;
    
                    cout<<endl;
                    stu[4].name = "zhangsan";
                    for(int i=0; i<5; i++) cout << v[i].name <<endl;
                
                    return 0;
            }       
        
            运行结果:
            name
            name
            name
            name
            name
    
            name
            name
            name
            name
            name
    
            例子分析:
            由于vector容器中存放的是副本,因此对原内容修改后,容器
            中的内容并不会发生改变。
    
        (2)例子:存放指针
            还是继续上面的例子,只是将容器中存放的数据改为指针。
            将主函数的内容修改为如下:
    
                Student *stu[5];
                std::vector<Student *> v(5);
    
                for(int i=0; i<5; i++) {
                        stu[i] = new Student("name");
                        v[i] = stu[i];
                }
    
                for(int i=0; i<5; i++) cout << v[i]->name <<endl;
    
                cout<<endl;
                stu[4]->name = "zhangsan";
                for(int i=0; i<5; i++) cout << v[i]->name <<endl;
    
    
            运行结果:
            name
            name
            name
            name
            name
    
            name
            name
            name
            name
            zhangsan
    
            例子分析:
            由于容器中存放的时指针,因此利用指针修改的是原对象的内容。   
    
    (4)访问(读写)vector容器中元素    
    (1)使用[]访问
        在之前访问vector容器的例子中,我们一直使用的都是[]的方式进行
        容器元素的当问。
        
    (2)迭代器访问
       (1)正向迭代器
        涉及的成员函数。
        begin():返回迭代器,它指向第一个元素
        end():返回迭代器,它指向最后一个元素后面的元素
        
        对迭代器可以++/--,+b/-n运算,使用*解引用后,就可以可以访问迭代器指向的元素内容。
        
        例子:
        #include <iostream>
        #include <stdio.h>
        #include <vector>
    
        using namespace std;
        class Student { 
        public:            
                Student(const string name=" "):name(name) { } 
                string name;
        };                  
    
        void show_vector(std::vector<Student *>::iterator first, std::vector<Student *>::iterator last) {
                for(; first!=last; first++) 
                        cout << (*first)->name <<endl;
        }
    
    
        int main(void)
        {
                Student *stu[5];
                std::vector<Student *> v(5);
    
                for(int i=0; i<5; i++) {
                        stu[i] = new Student("name");
                        v[i] = stu[i];
                }
    
                show_vector(v.begin(), v.end());
    
                (*(v.begin()+2))->name = "wangwu";
                (*(v.end()-1))->name = "lisi";
    
                cout<<endl;
                show_vector(v.begin(), v.end());
    
                return 0;
        }
        运行结果:
        name
        name
        name
        name
        name
    
        name
        name
        wangwu
        name
        lisi
        
        例子分析:
        
        (迭代器其实是一种抽象的指针,可以这么理解,所有需要解引用才可以访问)
        
        begin和end函数返回的是vcteor容器提供的随机迭代器,访问器所指
        向的元素时,需要使用*进行解引用,由于容器中存放的是对象的地址,
        因此访问对象的name时,需要使用->访问符。
    
        (2)反向迭代器
        vector提供的反向迭代器为std::vector<Student *>::reverse_iterator
        与之对应的是rbegin()和rend()函数。使用反向迭代器时,不能使用
        用begin()和end()函数,反之也是如此。
    
        请自己写代码验证反向迭代器。
        
    (3)直接访问元素内容     
        涉及的成员函数:
        (1)front():引用第一个元素
        (2)back():引用最后一个元素
        (3)at():引用指定索引的元素
    
        可以直接访问空间,不需要*解引用。
    
        #include <iostream>
        #include <stdio.h>
        #include <vector>
    
        using namespace std;
        class Student {
        public:
                Student(const string name=" "):name(name) { }
                string name;
        };
    
        void show_vector(std::vector<Student *> &v) {
                for(int i=0; i<v.size(); i++)
                        cout << v.at(i)->name <<endl;
        }
    
        int main(void)
        {
                Student *stu[5];
                std::vector<Student *> v(5);
    
                for(int i=0; i<5; i++) {
                        stu[i] = new Student("name");
                        v[i] = stu[i];
                }
    
                show_vector(v);
    
                v.front()->name = "wangwu";
                v.back()->name = "joinash";
                v.at(2)->name = "washion";
    
                cout<<endl;
                show_vector(v);
    
                return 0;
        }
        运行结果:
        name
        name
        name
        name
        name
    
        wangwu
        name
        washion
        name
        joinash
        
    (3)vector访问方式总结
        从前面的了解中,我们不难发现,vector的访问方式非常灵活,使用
        []/迭代器/直接访问等方式都可以。
        
    
        
    (5)使用vector提供的成员函数来添加/删除vector中的元素
    (1)涉及的成员函数
        (1)push_back():把参数(对象)添加到vector的最后位置
        (2)pop_back():删除vector尾部的元素
        (3)erase():删除任意位置的一个或者多个元素
        (4)clear():删除所有的元素
        (5)insert():在vector中的指定位置插入一个或多个对象。
            该函数提供了两个重载版本和一个函数模板。
            iterator insert ( iterator position, const T& x );
            void insert ( iterator position, size_type n, const T& x );
            template <class InputIterator> void insert ( iterator position, InputIterator first, InputIterator last );
        (6)empty():判断vector是否为空,避免对空vector进行操作。
            
            
    (2)例子
        #include <iostream>
        #include <stdio.h>
        #include <vector>
        #include <algorithm>
    
        void show_vector(std::vector<int>::iterator first, std::vector<int>::iterator end) {
                for( ;first!=end; first++) cout << *first << " ";
                cout << endl;
            cout << endl;
        }
    
        int main(void)
        {
                int buf[] = {1, 2, 3, 5, 4, 7, 8, 9, 0, 23, 54, 32};
                std::vector<int> v;
    
                cout << "将buf中下表[1-10)元素插入v,1-10是半开区间,含1不含10 "<<endl;
                v.insert(v.end(), buf+1, buf+10);
                show_vector(v.begin(), v.end());
    
                cout << "添加一个元素7到vector的末尾"<<endl;
                v.push_back(7);
                show_vector(v.begin(), v.end());
    
                cout << "删除最后一个元素" << endl;
                v.pop_back();
                show_vector(v.begin(), v.end());
    
                cout << "删除第2个到第5个半开区间的元素" << endl;
                v.erase(v.begin()+1, v.begin()+4);
                show_vector(v.begin(), v.end());
    
                cout << "在第4个元素未知插入元素111"<<endl;
                v.insert(v.begin()+3, 111);
                show_vector(v.begin(), v.end());
    
                return 0;
        }
        运行结果:
        将buf中下表[1-10)元素插入v,1-10是半开区间,含1不含10 
        2 3 5 4 7 8 9 0 23 
    
        添加一个元素7到vector的末尾
        2 3 5 4 7 8 9 0 23 7 
    
        删除最后一个元素
        2 3 5 4 7 8 9 0 23 
    
        删除第2个到第5个半开区间的元素
        2 7 8 9 0 23 
    
        在第4个元素未知插入元素111
        2 7 8 111 9 0 23 
    
        
    (6)迭代器的好处
    (1)数组传参操作
        (1)传统方式
            例子:求平均值
            #include <iostream>
            float average(float *buf, int count) {
                    int sum = 0;
                    for(int i=0; i<count; i++) {
                            sum += buf[i];
                    }
                    return sum/count;
            }
    
            int main(void)
            {
                float ret = 0;
                    float buf[] = {1, 2, 3, 5, 4, 7, 8, 9, 0, 23, 54, 32};
        
                    average(buf, sizeof(buf)/sizeof(buf[0]));
                
                    return 0;
            } 
    
            例子分析:
            上面显示了数组的经典传参方式,对于数组来说,必须传递两个参数,
            第一个是地址,第二是元素个数。
    
            但是对于字符串传参来说就不需要传递元素个数,字符串实际上是一
            个特殊形式的字符数组,由于字符串使用\0作为结尾标志,省去了需
            要传递元素个数的可能。
    
    
            函数模板实现求平均值:
            有的时候可能会对很多类型都要做求平均的运算,因此可以将求平均
            运算定义为一个模板,这样的话就可以根据情况的不同,生成各种不
            同求平均值的函数实例。
            #include <iostream>
            template <class T1> float average(T1 *buf, int count) {
                    T1 sum = 0;
                    for(int i=0; i<count; i++) {
                            sum += buf[i];
                    }   
                    return sum/count;
            }       
        
            int main(void)
            {
                    float ret = 0;
                    float buf[] = {1, 2, 3, 5, 4, 7, 8, 9, 0, 23, 54, 32};
            
                    ret = average(buf, sizeof(buf)/sizeof(buf[0]));
                    cout <<"平均值="<< ret << endl; 
            
                    return 0;
            }    
        
        (2)传递首尾指针方式(迭代器)
            #include <iostream>
            float average(float *first, float *last) {
                    int sum = 0;
                    int count = last - first;
                    for( ; first!=last; first++) {
                            sum += *first;
                    }   
                    return sum/count;
            }
            int main(void)
            {
                    float ret = 0;
                    float buf[] = {1, 2, 3, 5, 4, 7, 8, 9, 0, 23, 54, 32};
    
                    ret = average(buf, buf+sizeof(buf)/sizeof(buf[0]));
                    cout <<"平均值="<< ret << endl;
    
                    return 0;
            }
    
             函数模板实现求平均值:    
            前面提到过,指针本身就是一种特殊的迭代器,对于数组的传参,
            可以使用传递首尾指针(半开区间)的方式。
    
            #include <iostream>
            template <class iter> float average(iter first, iter last) {
                    int sum = 0;
                    int count = last - first;
                    for( ; first!=last; first++) {
                            sum += *first;
                    }
                    return sum/count;
            }
        
            int main(void)
            {
                    float ret = 0;
                    float buf[] = {1, 2, 3, 5, 4, 7, 8, 9, 0, 23, 54, 32};
    
                    ret = average(buf, buf+sizeof(buf)/sizeof(buf[0]));
                    cout <<"平均值="<< ret << endl;
    
                    return 0;
            }
    
            例子分析:
            由于没有传递元素个数,所以需要使用首尾指针相减得到元素
            个数。
    
    
    (2)vector传参操作
        (1)普通方式
            #include <iostream>
            #include <vector>
    
            float average(std::vector<int> &v) {
                    int sum = 0;
                    int count = v.size();
                    for(int i; i<v.size(); i++) {
                            sum += v[i];
                    }
                    return sum/count;
            }
    
            int main(void)
            {
                    float ret = 0;
                    float buf[] = {1, 2, 3, 5, 4, 7, 8, 9, 0, 23, 54, 32};
                    std::vector<int> v(buf, buf+sizeof(buf)/sizeof(buf[0]));
    
                    ret = average(v);
                    cout <<"平均值="<< ret << endl;
    
                    return 0;
            }
            例子分析:
            将vector对象直接以引用方式进行传参操作。
    
           函数模板求平均值:
            #include <iostream>
            #include <vector>
            template<class T> float average(T &v) {
                    int sum = 0;
                    int count = v.size();
                    for(int i; i<v.size(); i++) {
                            sum += v[i];
                    }
                    return sum/count;
            }
    
            int main(void)
            {
                    float ret = 0;
                    float buf[] = {1, 2, 3, 5, 4, 7, 8, 9, 0, 23, 54, 32};
                    std::vector<int> v(buf, buf+sizeof(buf)/sizeof(buf[0]));
    
                    ret = average(v);
                    cout <<"平均值="<< ret << endl;
    
                    return 0;
            }
    
        (2)迭代器  
            #include <iostream>
            #include <vector>   
            float average(std::vector<int>::iterator first, std::vector<int>::iterator last) {
                    int sum = 0;
                    int count = last - first;
                    for( ; first!=last; first++) {
                            sum += *first;
                    }
                    return sum/count;
            }
    
            int main(void)
            {
                    float ret = 0;
                    float buf[] = {1, 2, 3, 5, 4, 7, 8, 9, 0, 23, 54, 32};
                    std::vector<int> v(buf, buf+sizeof(buf)/sizeof(buf[0]));
    
                    ret = average(v.begin(), v.end());
                    cout <<"平均值="<< ret << endl;
    
                    return 0;
            }
    
            例子分析:
            从这个例子你会发现,这个vector迭代器的传参与传递数组
            首尾指针的方式时一样的,从这一点你也可以看出,指针其
            实就是迭代器的原始实现方式。
    
           函数模板求平均值:
            template<class iter> float average(iter first, iter last) {
                    int sum = 0;
                    int count = last - first;
                    for( ; first!=last; first++) {
                            sum += *first;
                    }   
                    return sum/count;
            }
    
            int main(void)
            {
                    float ret = 0;
                    float buf[] = {1, 2, 3, 5, 4, 7, 8, 9, 0, 23, 54, 32};
                    std::vector<int> v(buf, buf+sizeof(buf)/sizeof(buf[0]));
    
                    ret = average(v.begin(), v.end());
                    cout <<"平均值="<< ret << endl;
    
                    return 0;
            }
            
            例子分析:
            这个与传递数组首尾指针的方式是完全一样的,只是这里使
            用的不是普通的指针,使用的是由容器自己提供的迭代器。
    
        
    (3)求用输入输出流迭代器获取到的数据的平均值
    
       (1)输入流迭代器
        
        前面的例子中都是将数据先存入数组或者vector容器。
    
        当希望对输入数据求平均值时,传统的做法是先将输入数据存放到数组或
        者vector后,再调用average函数求平均值。
    
        但是如果使用输入输出流迭代器的话,可以省去将数据暂存到数组或者
        vector环节。
    
        例子:
        #include <iostream>
        #include <stdio.h>
        #include<iterator>
    
        template<class iter> float average(iter first, iter last) {
                int sum = 0;
                int count = 0;
                for( ; first!=last; first++, count++) {
                        sum += *first;
                }   
                return sum/count;
        }
          
        int main(void)
        {
                float ret = 0;
    
                cout << "请输入一组需要求平均值的数,之用空格分隔" << endl;     
                ret = average(istream_iterator<float>(cin), istream_iterator<float>());
                cout <<"平均值="<< ret << endl; 
            
                return 0;
        }   
            
        例子分析:
        例子中,直接使用输入迭代器从输入流cin中获取数据,但是count中不
        能直接通过迭代器相减的方式得到,因为输入的个数不能立即确定,所
        以只能使用count++的方式计算count。
        
    
        改变输入迭代器的输入流:
        对于输入迭代器来说,给定不同的输入流可以对不同来源的数据进行操作,
        比如下面的这个例子:
    
        #include <iostream>
        #include<iterator>
        #include<sstream>
    
        template<class iter> float average(iter first, iter last) {
                int sum = 0, count = 0;
                for( ; first!=last; first++, count++) {
                        sum += *first;
                }
                return sum/count;
        }
    
        int main(void)
        {
                float ret = 0;
                string str = "1 34 45 67 78 44 33";
                istringstream iss(str);
    
                ret =average(std::istream_iterator<float>(iss), std::istream_iterator<float>());
                cout <<"平均值="<< ret << endl;
    
                return 0;
        }
    
        例子分析:
        输入迭代器中,将字符串输入流作为了输入迭代器的参数,因此,输
        入的数据来自于字符串。
                
    
        (2)输出流迭代器
        如果希望在averae函数中将所有的数据显示出来,除了可以使用循环
        打印外,还可以使用输出流迭代器实现。
    
        例子:
        #include <iostream>
        #include <algorithm>
        #include<iterator>
    
        void show_vector(int *first, int *last) {
                std::copy(first, last, ostream_iterator<int>(cout, " "));
                cout << endl;
        }
    
        int main(void)
        {
                int buf[] = {4, 2, 5, 1, 3, 7, 8, 45, 32, 12};
    
                show_vector(buf, buf+sizeof(buf)/sizeof(buf[0]));
    
                return 0;
        }
        例子分析:
        直接将指针当作迭代器使用,
        std::copy(first, last, ostream_iterator<int>(cout, " "));
            
        调用了算法copy函数,该函数的表示,将迭代器first和last之间的
        数据复制给输出迭代器,最后输出迭代器利用cout将数据输出显示,
        数据之间使用" "间隔。
    
        如果输出流并不是cout,而是一个普通文件流,那么数据将会被输入
        到文件中。
        
        
    
    (4)定义一个对数组/vector/输入迭代器都适用的average函数模板
    
        通过起那面的例子,不难发现,通过迭代器的使用,完全可以定义一个
        针对数组/vector/输入迭代器都适用的average函数模板,由此可以看
        出迭代器的好处。
    
        #include <iostream>
        #include <algorithm>
        #include <vector>
        #include<iterator>
    
        template<class iter> float average(iter first, iter last) {
                int sum = 0, count = 0;
                for( ; first!=last; first++, count++) {
                        sum += *first;
                }   
                return sum/count;
        }   
    
        int main(void)
        {
                float ret = 0;
                float buf[] = {4, 2, 5, 1, 3, 7, 8, 45, 32, 12};
                std::vector<float> v(buf, buf+sizeof(buf)/sizeof(buf[0]));
    
                cout<<"1.计算数组中数据的平均值" <<endl;
                cout<<"2.计算vector容器中数据的平均值" <<endl;
                cout<<"3.计算从键盘输入数据的平均值" <<endl;
                int select = 0;
                cin >> select;
    
                if(1 == select) {
                        ret = average(buf,  buf+sizeof(buf)/sizeof(buf[0]));
                } else if(2 == select) {
                        ret = average(v.begin(),  v.end());
                } else if(3 == select) {
                        cout << "请输入一组需要求平均值的数,使用空格分隔" << endl;
                        ret =average(std::istream_iterator<float>(cin), std::istream_iterator<float>());
                }
    
                cout <<"平均值="<< ret << endl;
    
                return 0;
        }
    
        例子分析:
        有三种不同的选择,分别对数组/vector容器/输入的数据进行求平均
        值,但是这三种情况下使用的是同一个模板,这个模板会根据不同的
        情况生成不同的函数实例。
    

    相关文章

      网友评论

          本文标题:标准模板STL-vector

          本文链接:https://www.haomeiwen.com/subject/aajilqtx.html