标准模板库、容器类、迭代器、函数对象
作者:互联网
标准模板库
-
迭代器
-
迭代器能够用来遍历容器的对象;函数对象是类似于函数的对象,可以是类对象或函数指针(包括函数名因为函数名被用作指针);STL 不是面向对象的编程,而是泛型编程;
-
模板类 vector p546
-
STL 在头文件 vector 中定义了一个 vector 模板;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
与 string 类相似,各种 STL 容器模板都接受一个可选的模板参数,该参数指定使用哪个分配器对象来管理内存。如,vector 模板的开头与下面类似:
template <class T, class Allocator = allocator<T>>
class vector{...}
如果该模板省略参数的值,则容器模板将默认使用 allocator<T> 类。这个类使用 new 和 delete。
-
对矢量可执行的操作 p547
size() :返回容器中元素数目 swap():交换两个容器的内容 begin():返回一个指向容器中第一个元素的迭代器 end():返回一个表示超过容器尾的迭代器,即 end() 成员函数标识超过结尾的位置 push_back():将元素添加到矢量末尾 erase():删除矢量中给定区间的元素;它接受两个迭代器参数,第一个迭代器指向区间的起始处,第二个迭代器指向区间终止处的后一个位置 insert():接受 3 个迭代器参数,第一个参数指定新元素插入的位置,第二个和第三个爹嗲气参数定义了被插入区间
每个容器类都定义了一个合适的迭代器;要为 vector 的 double 类型规范声明一个迭代器,可以:
vector<double>::iterator pd; // pd an iterator
vector<double> scores;
pd = scores.begin(); // have pd point to the first element
*pd = 22.3;
++pd;
此外,在初始化迭代器时,也可以使用 auto :
auto pd = scores.begin(); // C++11 automatic type deduction
-
STL 从更广泛的角度定义了非成员(non-member)函数来执行这些操作,即不是为每个容器类定义 find() 函数,而是定义了一个适用于所有容器类的非成员函数 find()。另一方面,即使有执行相同任务的非成员函数,STL 有时也会定义一个成员函数,这是因为对有些操作来说,类特定算法比通用算法高,例如,vector 的成员函数 swap() 的效率比非成员函数 swap() 高。 p550
3 个具有代表性的 STL 函数:for_each()、random_shuffle() 和 sort():
-
for_each()
for_each() 接受 3 个参数,前两个是定义容器中区间的迭代器,最后一个是一个函数对象;for_each() 函数将被指向的函数应用于容器区间中的各个元素;被指向的元素不能修改容器元素的值。可以用 for_each() 函数来代替 for 循环,如:
struct Review{
std::string title;
int rating;
};
...
vector<Review> books;
...
vector<Review>::iterator pr;
for (pr = books.begin(); pr != books.end(); pr++)
ShowReview(*pr);
替换为:
for_each(books.begin(), books.end(), ShowReview);
这样可以避免显式地使用迭代器变量。
-
random_shuffer()
Random_shuffer() 函数接受两个指定区间地迭代器参数,并随机排列该区间中的元素。例如,下面的语句随机排列 books 矢量中的所有元素:
random_shuffle(books.begin(), books.end())
与可用于任何容器类的 for_each() 不同,该函数要求容器类允许随机访问,vector 类可以做到这一点。
-
sort()
sort() 函数也要求容器支持随机访问。该函数有两个版本,第一个版本接受两个定义区间的迭代器参数,并使用为存储在容器中的 < 运算符,对区间中的元素进行操作。例如,下面的语句按升序对 coolstuff 的内容进行排序,排序时使用内置的 < 运算符对值进行比较:
vector<int> coolstuff;
...
sort(coolsutff.begin(), coolstuff.end());
如果容器元素是用户自定义的对象,则要使用 sort(),必须定义能够处理该类型对象的 operator<() 函数(即重载 < 运算符);即,如果为 Review 提供了成员或非成员函数 operator<(),则可以对包含 Review 对象的矢量进行排序。
由于
Review 是一个结构,其成员是公有的,因此可以定义这样的非成员函数(不需是友元)
book operator<(const Review & r1, const Review & r2)
{
if (r1.title < r2.title)
return true;
else if (r1.title == r2.title && r1.rating < r2.rating)
return true;
else
return false;
}
有了上述函数后,可以对包含 Review 对象(如 books)的矢量进行排序:
sort(books.begin(), books.end());
如果按照降序排序,可以使用第二个版本的 sort(),它接受 3 个参数,前两个参数是指定区间的迭代器,最后一个参数是函数对象。
book WorseThan(const Review & r1, const Review & r2)
{
if (r1.rating < r2.rating)
return true;
else
return false;
}
...
sort(books.begin(), books.end(), WorseThan);
-
基于范围的 for 循环(C++11)
基于范围的 for 循环是为用于 STL 而设计的,以下是一个示例
double prices[5] = {4.99, 10.99, 6.87, 7.99, 8.49};
for (double x : prices)
cout << x << std::endl;
在这种 for 循环中,括号内的代码声明一个类型与容器存储的内容相同的变量,然后指出了容器的名称;接下来,循环体使用指定的变量一次访问容器的每个元素。例如,对于:
for_each(books.begin(), books.end(), ShowReview);
可以更改为:
for (auto x : books) ShowReview(x);
不同于 for_each(),基于范围的 for 循环可以修改容器的内容(利用将参数设置为引用的方法):
void InflateReview(Review &r){r.rating++;}
可使用如下循环对 books 的每个元素执行该函数:
for (auto & x : books) InflateReview(x);
标签:容器,begin,函数,迭代,vector,books,模板 来源: https://www.cnblogs.com/San-Francisco/p/16322516.html