c++(标准模板库STL)

时间:2024-11-16 07:07:16

STL是一种泛型编程(generic programming)

  • STL提供了一组表示容器、迭代器、函数对象和算法的模板。
  • 面向对象编程关注的是编程的数据方面,而泛型编程关注的是算法
  • 他们之间的共同点是抽象和创建可重用代码,但是他们的理念截然不同。

1、容器(container

  • 容器类是一个与数组类似的单元,但是他是管理序列的类,也是容纳一组对象对象集的类。
  • 通过容器类提供的成员函数,可以实现例如向序列中插入、删除、查找元素等操作;
  • 这些成员函数通过返回迭代器来指定元素在序列中的位置。

容器主要有以下分类:

二、泛型算法(generic algorithm)

  • 模板中的算法不依赖与具体的数据类型,而泛型算法更进一步不依赖于具体的容器。
  • 这也是STL最大的优点,就是他提供能在各种容器中通用的算法,例如:插入、排序、查找、删除等。
  • 一种算法可以适用于多种容器,故称为泛型算法;
  • 泛型算法之所以能够用于各种容器,是因为有迭代器。

三、迭代器(iterator)

  • STL设计的精髓在于把容器和算法分开,彼此独立设计,最后再用迭代器把他们合并在一起。

  • 迭代器是一种数据类型,他提供了一种方法,可以顺序访问一个容器中的每个元素,而又不暴露该对象的内部表示

  • 迭代器的用法和指针类似,只不过它相当于一个智能指针,它指向容器内部的数据,并可以通过解引用*来获取它指向的数据。

  • STL提供的所有容器都有这样的迭代器,用以存取他们所管理的元素序列。

例如:

容器的成员函数begin()返回指向容器中第一个元素的迭代器;end()返回指向容器中最后一个元素后继位置的迭代器。

下面通过STL中提供的一个泛型函数find()来说明迭代器与泛型算法的关系:

首先看下STL对于find函数的内部实现:

  1. template <class input_iterator_tag,class T>
  2. input_iterator_tag find(input_iterator_tag first,input_iterator_tag last,const T value)
  3. {
  4. for(;first != last;first++)
  5. {
  6. if(value == *first)
  7. return first;
  8. }
  9. return last;
  10. }

注意:

  • 源码中出现的input_iterator_tag是一个输入迭代器类,它的功能是从容器中读取元素。
  • 第一个参数和第二个参数给出了find函数要查找的范围,这个范围是一个左闭右开的区间:[first, last),last对应的元素不在查找范围内。
  • 这是一个普遍的约定,所有的泛型算法都遵守这个约定,在后面的程序中还会遇到的。

然后在应用程序中测试:

  1. #include <iostream>
  2. #include <algorithm>
  3. using namespace std;
  4. int main()
  5. {
  6. int num[] = {1,2,3,4,5};
  7. int *result,value;
  8. cout << "please input the num you want to search:" ;
  9. cin>>value;
  10. result = find(num,num+5,value); //注意这里模板参数被特化为int *
  11. if(result == num+5)
  12. cout<<"can't find the num you input\n\n";
  13. else
  14. cout<<"find it!,the index is:"<<result-num<<endl;
  15. return 0;
  16. }

运行结果:

结合find()函数的源码可以知道,泛型算法不直接访问容器的的元素,与容器无关。元素的全部访问和遍历都通过迭代器实现,并不需要知道容器的类型。

四、顺序容器之矢量类

  • 矢量vector类是一个多功能、能够操作多种数据结构和算法的模板类和函数库。
  • 它和数组类似,通过下标运算符访问矢量中的元素,并且其元素具有连续的内存地址
  • vector类的一大优点是,他可以进行动态的内存管理。并且该类内部包含很多常用的函数、特有函数,用以实现堆栈、队列、列表等结构。

每种容器都有自己支持的迭代器类型,迭代器决定了可采用哪种算法。vector支持随机访问迭代器,能直接访问容器中的任意元素,功能比较强大。选择所需容器类实际上很大部分是选择所支持的迭代器。

下面通过一个简单的demo演示vector类的应用:

  1. #include <iostream>
  2. #include <algorithm>
  3. #include <vector>
  4. using namespace std;
  5. int main()
  6. {
  7. double values[] = {1,2,3,4,5,6,7};
  8. int i;
  9. //构造一个向量
  10. vector<double> dVector(values,values+7);
  11. cout<<" value is:";
  12. for(i=0;i<dVector.size();i++)
  13. cout<<dVector[i]<<"\t";
  14. cout<<endl;
  15. dVector.assign(4,1.5); //1.5复制4
  16. cout<<" assign,the value is:";
  17. for(i=0;i<dVector.size();i++)
  18. cout<<dVector[i]<<"\t";
  19. cout<<endl;
  20. dVector.at(0) = 34.3; //给向量中的第一个元素赋值
  21. cout<<" the at,the value is::";
  22. for(i=0;i<dVector.size();i++)
  23. cout<<dVector[i]<<"\t";
  24. cout<<endl;
  25. //将首元素的迭代器赋值给itr
  26. vector<double>::iterator itr = ();
  27. (itr+1,55);
  28. (itr+1,66);
  29. (()+1,0); //这个用法和上面的用法一样
  30. cout<<"4.:after insert,the value is:";
  31. for(i=0;i<dVector.size();i++)
  32. cout<<dVector[i]<<"\t";
  33. cout<<endl;
  34. return 0;
  35. }

运行结果:

更多vector类的成员函数可以访问: /reference/vector/vector/?kw=vector