标准模板库小记



  • 标准模板库

    • STL提供了一组表示容器,迭代器,函数对象和算法的模板。容器是一个与数组类似的单元,可以存储若干个值。STL容器是同质的,即存储的值的类型相同;算法是完成特定任务的处方;迭代器能够用来遍历容器的对象,是广义指针;函数对象是类似于函数的对象,可以是类对象或函数指针。
    • STL不是面向对象编程,而是泛型编程
    1.模板类vector
    • 在头文件vector中定义了vector模板

    • 要创建vector模板对象,可以使用通常的<type>表示法来指出要使用的类型。另外,vector模板使用动态内存分配,因此可以用初始化参数来指出需要多少矢量
      #include vector
      using namespace std;
      vector<int> ratings(5);// a vector of 5 ints
      int n;
      cin >> n;
      vector<double> scores(n);//a vector of n doubles
      由于[]被重载,因此创建vector对象后可使用通常的数组表示法来访问各个元素:
      ratings[0] = 9;
      for(int i = 0; i<n ; i++)
          cout << scores[i] << endl;
      
      分配器:与string类相似。各种STL容器模板都提供一个可选的模板参数,该参数指定使用哪个分配器对象来管理内存。例如vector模板的开头与下面类似:
      template <class T, class allocator = allocator<T>>
      	class vector{...
      如果省略该模板参数的值,则容器模板将默认使用allocator<T>类。这个类使用new和delete
      
    • 可对矢量执行的操作:所有的STL容器都提供了一些基本方法,包括size()--返回容器中元素数目,swap()--交换两个容器的内容,begin()--返回一个指向容器中第一个元素的迭代器,end()--返回一个表示超过容器尾的迭代器;迭代器是一个广义指针。事实上,它可以是指针,也可以是一个可对其执行类似指针的操作---如*和++的对象。每个容器类都定义了一个合适的迭代器,该迭代器的类型是一个名为iterator的typedef,其作用域为整个类
      //例如要为vector的double类型规范声明一个迭代器
      vector<double>::iterator pd;
      vector<double> scores;
      pd = scores.begin();
      *pd = 22.3;
      ++pd;
      还有一个c++11自动类型推断很有用的地方,例如:
      auto pd = scores.begin();
      end()成员函数标识超过结尾的位置
      for (pd = scores.begin();pd!=scores.end();pd++)
          cout << *pd <<endl;
      
      push_back()是一个方便的方法,它将元素添加到矢量末尾。这样做时,它将负责内存管理,增加矢量的长度,使之能够容纳新的成员。
      vector<double> scores;
      double temp;
      while(cin>>temp&&temp>=0)
          scores.push_back(temp);
      
      erase()方法删除矢量中给定区间的元素。它接受2个迭代器参数,它们定义了要删除的区间。其中第一个迭代器指向区间的起始处,第二个迭代器位于区间终止处的后一个位置。
      scores.erase(scores.begin(),scores.begin()+2);
      
      insert()方法的功能与erase()相反。它接受3个迭代器参数,第一个参数指定了新元素的插入位置,第二个和第三个迭代器参数定义了被插入区间,该区间通常是另一个容器对象的一部分
      vector<int> old_v;
      vector<int> new_v;
      old_v.insert(old_v.begin(),new_v.begn()+1,new_v.end());
      //上述代码将矢量new_v中除第一个元素外的所有元素插入到old_v矢量的第一个元素前面
      
      
    • 对矢量可执行的其他操作:比如搜索,排序,随机排序等。但矢量模板并未包含执行这些常见操作的方法。STL从更广泛的角度定义了非成员函数来执行这些操作,即不是为每个容器定义find()成员函数,而是定义了一个适用于所有容器类的非成员函数find()。这样省去了大量重复操作
      来看3个具有代表性的STL函数:for_each(),random_shuffle()和sort()。
      (1)for_each()函数可用于很多容器类,它接受3个参数。前2个是定义容器中区间的迭代器,最后一个是指向函数的指针(更普遍的说,最后一个参数是一个函数对象,函数对象将稍后介绍)。此函数将被指向的函数应用于容器区间的各个元素。被指向的函数不能修改容器元素的值。可以用for_each()循环来代替for循环
      例如,可将
      vector<Review>::iterator pr;
      for (pr = books.begin();pr != books.end(); pr++)
          ShowReview(*pr);
      替换为:
      for_each(books.begin(),books.end(),ShowReview);//这样可避免显示地使用迭代器变量
      (2)Random_shuffle()函数接受两个指定区间的迭代器参数,并随机排列该区间中的元素。
      例如,下面的参数随机排列books矢量中所有元素
      random_shuffle(books.begin(),books.end());
      //与可用于任何容器类的for_each不同,该函数要求容器类允许随机访问,vector类可以做到这一点
      (3)sort()函数也要求容器支持随机访问。该函数有2个版本,第一个版本接受两个定义区间的迭代器参数,并使用为存储在容器中的类型元素定义的<运算符,对区间中的元素进行操作。
      例如,下面的语句按升序对cool的内容进行排序
      vector<int> cool;
      sort(cool.begin(), cool.end());
      //如果容器元素是用户定义的对象,则要使用sort(),必须定义能够处理该类型对象的operator<()函数
      第二个版本接受3个参数,前2个参数也是指定区间的迭代器,最后一个参数是指向要使用的函数的指针
      
    • 基于范围的for循环c++11:
      for_each(books.begin(),books.end(),ShowReview);
      可修改为
      for (auto x: books) ShowReview(x);
      //根据books的类型(vector<Review>),编译器将推断出x的类型为Review,而循环将依次将books中的每个Review对象传递给ShowReview()
      不同于for_each(),基于范围的for循环可以修改容器的内容,诀窍是指定一个引用参数
      例如,假设有如下函数
      void Inflate(Review &r){r.rating++};
      可使用如下循环对books的每个元素执行该函数:
      for (auto &x:books) Inflate(x);
      

 

Copyright © 2018 bbs.dian.org.cn All rights reserved.

与 Dian 的连接断开,我们正在尝试重连,请耐心等待