标准模板库小记
-
标准模板库
- 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);