当 std::istream_iterator<int>(std::cin) 等于结束迭代器 std::istream_iterator<int>()

问题描述

我正在通过检查/编写不同的示例来学习迭代器。在一个这样的例子中(下面给出),当我在输入流中输入一个无效类型说 char 时,下一个 cout 语句不会被执行。示例如下:

#include <iostream>
#include <iterator>
int main()
{
   
    std::istream_iterator<int> starting_it(std::cin),ending_it;
   
    while(starting_it != ending_it)
    {
       
       *starting_it++;//lets say i entered the character f on the console and pressed enter then why is the next cout statement not executed
       std::cout<<"after"<<std::endl;//this line is not printed on the console after an invalid type is encountered
    }
    return 0;
}

现在当我执行这个程序并输入值时说 1 2 f 然后按回车键,然后控制台上只打印两个“之后”。 我的问题是为什么“after”没有在屏幕上打印 3 次?

这就是我认为正在发生的事情:

第 1 步。因为一开始 starting_itending_it 不相等,所以我们进入 while 循环。

第 2 步。现在,starting_it 递增,同时从 cin 中读取一个值。

第 3 步。接下来,返回 starting_it 的旧值,我们对其应用 * 运算符。这在当前迭代中具有值 1,它在语句结束时被丢弃。下一个 cout<<"after"<<std::endl; 被执行并打印在控制台上。

第 4 步。现在再一次,因为我们没有遇到文件结束或任何输入错误,所以我们进入 while 循环的下一次迭代。

步骤 5。重复步骤 1-步骤 4。这次唯一的区别是,在 Step4 结束时,当我们取消引用 starting_it 时,我们得到了值 2。

第六步。现在我们再次进入下一次迭代。但是这次当 starting_it 递增时,读取的字符类型无效,因此 starting_it 等于结束迭代器。

现在我的问题是在该步骤中应该执行语句std::cout<<"after"<<std::endl,并且应该在控制台上打印“after”。然后应该检查 while 的条件。出来是假的。但为什么这没有发生呢?为什么我们在控制台上只打印了两个“after”而不是 3 个。是不是因为 ostream 也出错了。实际上,似乎每当我们在输入流上遇到错误或 eof 时,我们就会跳出 while 循环。另外,我的解释是否正确,如果不正确,请纠正我。

我附上了输出的截图。

screenshot

解决方法

std::istream_iterator 预读:构造函数中的第一次读取,operator++ 中的后续读取。 operator* 返回先前读取的缓存值。如果任何读取失败,迭代器就等于结束迭代器。

这就是您的示例中发生的情况。 starting_it 在构造函数中读取 1。循环的第一次迭代读取 2 并打印第一个 after。循环的第二次迭代尝试读取 f(此时 starting_it 变为等于 ending_it)并打印第二个 after。那么循环存在。

总共执行了三个读取 - 一个在构造函数中,两个在两个 operator++ 调用中,对应于打印了两次 after