在经过各种STL算法(例如std :: find , std :: equal , std :: count)的模板定义之后,您必须找到由Input Iterator类型的对象组成的模板定义。那么它们是什么?为什么要使用它们?
输入迭代器是C++标准库中存在的五种主要迭代器之一,其他是输出迭代器,正向迭代器,双向迭代器, 和随机访问迭代器。
根据输入迭代器的功能以及使用它们可以实现的功能,在所有可用的迭代器中,输入迭代器被认为是最弱的也是最简单的。它们是可用于顺序输入操作的迭代器,其中迭代器指向的每个值都是只读的,然后迭代器递增。
要记住的一件事是,前向,双向和随机访问迭代器也是有效的输入迭代器,如上面的迭代器层次结构所示。
显着特征
- 可用性:输入迭代器只能与单遍算法一起使用,即,我们最多可以一次访问范围内的所有位置的算法,例如当我们必须搜索或查找范围内的任何元素时,位置最多一次。
- 相等/不相等比较:可以将输入迭代器与另一个迭代器进行相等性比较。由于迭代器指向某个位置,因此这两个迭代器仅在指向相同位置时才相等,否则就不相等。
因此,如果A和B是输入迭代器,则以下两个表达式有效:
A == B // Checking for equality
A != B // Checking for inequality
3.取消引用:可以使用运算符*和->作为右值来取消引用输入迭代器,以获取存储在迭代器指向的位置上的值。
因此,如果A是输入迭代器,则以下两个表达式有效:
*A // Dereferencing using *
A -> m // Accessing a member element m
4.可递增的:可以使用运算符++()递增输入迭代器,以使其引用序列中的下一个元素。
注意:我们可以将输入迭代器与增量运算符一起使用的事实并不意味着运算符–-()也可以与它们一起使用。请记住,输入迭代器是单向的,只能向前移动。
因此,如果A是输入迭代器,则以下两个表达式有效:
A++ // Using post increment operator
++A // Using pre increment operator
可交换的:这些迭代器指向的值可以交换或交换。
实际实施
了解了它的特性和不足之后,了解其实际实现也非常重要。如前所述,仅当我们要访问元素时才使用输入迭代器,而不必在必须为其分配元素时使用。以下两种STL算法可以显示这一事实:
- std :: find:据我们所知,该算法用于查找容器内元素的存在。因此,让我们看一下它的内部工作原理(不要只关注输入迭代器可以在哪里使用以及不能在哪里使用):
CPP
// Definition of std::find() template
InputIterator find (InputIterator first, InputIterator last,
const T& val)
{
while (first!=last)
{
if (*first==val) return first;
++first;
}
return last;
}
CPP
// Definition of std::copy() template
OutputIterator copy(InputIterator first, InputIterator last,
OutputIterator result)
{
while (first != last)
*result++ = *first++;
return result;
}
CPP
// C++ program to demonstrate input iterator
#include
#include
using namespace std;
int main()
{
vector v1 = { 1, 2, 3, 4, 5 };
// Declaring an iterator
vector::iterator i1;
for (i1 = v1.begin(); i1 != v1.end(); ++i1) {
// Accessing elements using iterator
cout << (*i1) << " ";
}
return 0;
}
- 因此,这是输入迭代器,单遍算法的实际实现,其中仅我们必须顺序移动并访问元素,并检查与另一个元素的相等性,就像上面使用的第一个一样,因此可以在此处使用它们。更多此类算法为std :: equal , std :: equal_range和std :: count。
- std :: copy:顾名思义,此算法用于将一个范围复制到另一个范围。现在,就访问元素而言,输入迭代器很好,但是一旦我们必须在另一个容器中分配元素,就不能为此目的使用这些输入迭代器。
CPP
// Definition of std::copy() template
OutputIterator copy(InputIterator first, InputIterator last,
OutputIterator result)
{
while (first != last)
*result++ = *first++;
return result;
}
- 在这里,由于结果是分配给元素的结果容器的迭代器,因此,为此,我们不能使用输入迭代器,而要在其位置使用输出迭代器,而对于第一个,只需要对其进行递增和访问后,我们使用了输入迭代器。
局限性
在研究了显着特征之后,还必须知道它的不足,这使其成为所有迭代器中最弱的迭代器,在以下几点中提到:
- 仅访问,不分配:最大的缺点之一是我们不能向该迭代器指向的位置分配任何值,它只能用于访问元素,而不能分配元素。
CPP
// C++ program to demonstrate input iterator
#include
#include
using namespace std;
int main()
{
vector v1 = { 1, 2, 3, 4, 5 };
// Declaring an iterator
vector::iterator i1;
for (i1 = v1.begin(); i1 != v1.end(); ++i1) {
// Accessing elements using iterator
cout << (*i1) << " ";
}
return 0;
}
输出:
1 2 3 4 5
上面是使用输入迭代器访问元素的示例,但是,如果我们执行以下操作:
*i1 = 7;
- 因此,输入迭代器中不允许这样做。但是,如果对上面的代码尝试此操作,则它将起作用,因为向量在层次结构中返回的迭代器要比输入迭代器高。
巨大的缺陷是为什么很多算法(如std :: copy)需要将一个范围复制到另一个容器中,而不能将输入迭代器用于结果容器,因为我们不能使用此类迭代器为其分配值,而只能使用输出迭代器。 - 不能递减:就像我们可以对输入迭代器使用运算符 ++()来递增它们一样,我们也不能递减它们。
If A is an input iterator, then
A-- // Not allowed with input iterators
- 在多遍算法中使用:由于它是单向的并且只能向前移动,因此,此类迭代器不能用于需要多次处理容器的多遍算法中。
- 关系运算符:尽管输入迭代器可以与相等运算符(==)一起使用,但不能与其他关系运算符(如<=)一起使用。
If A and B are input iterators, then
A == B // Allowed
A <= B // Not Allowed
- 算术运算符: -等方面的关系运算符相似,而且还不能与算术运算运算符如+,使用。这意味着输入运算符只能沿太过向前和太过顺序的方向移动。
If A and B are input iterators, then
A + 1 // Not allowed
B - 2 // Not allowed