首页 > 解决方案 > 为什么从分配给变量的 istream_iterator 读取不起作用?

问题描述

我编写了以下程序,它从 中读取 3 个数字std::cin,并将它们输出到std::cout,并执行两次:

#include <iostream>
#include <algorithm>
#include <iterator>

int main()
{
    std::copy_n(std::istream_iterator<int>(std::cin), 
                3, 
                std::ostream_iterator<int>(std::cout, " "));
    
    std::copy_n(std::istream_iterator<int>(std::cin), 
                3, 
                std::ostream_iterator<int>(std::cout, " "));              
}

对于 的输入1 2 3 4 5 6,程序会打印预期的1 2 3 4 5 6


当我发现代码有点冗长时,我尝试将迭代器存储在变量中:

#include <iostream>
#include <algorithm>
#include <iterator>

int main()
{
    auto ins = std::istream_iterator<int>(std::cin);
    auto outs = std::ostream_iterator<int>(std::cout, " ");
               
    std::copy_n(ins, 3, outs);
    std::copy_n(ins, 3, outs);
}

但现在对于输入1 2 3 4 5 6,程序会打印 1 2 3 1 4 5

我不明白输出。这里发生了什么,我做错了什么?

另外,请注意,它仅在我使用ins. 我是否使用outs不影响输出。

标签: c++iteratoristream-iterator

解决方案


根据此参考

std::istream_iterator 是单通道输入迭代器,通过调用适当的运算符>>,从为其构造它的 std::basic_istream 对象读取类型 T 的连续对象。实际的读取操作是在迭代器递增时执行的,而不是在取消引用时执行的。构造迭代器时读取第一个对象。取消引用仅返回最近读取的对象的副本。

因此,当您第一次创建ins变量时,它会立即读取1cin缓存它。

如果查看 的声明,输入迭代器是按值copy_n()传递的,这意味着它是被复制的。

template< class InputIt, class Size, class OutputIt >
OutputIt copy_n( InputIt first, Size count, OutputIt result );

为了论证的缘故,我们假设copy_n()正在使用以下实现(检查编译器的实际实现):

template< class InputIt, class Size, class OutputIt>
OutputIt copy_n(InputIt first, Size count, OutputIt result)
{
    if (count > 0) {
        *result++ = *first;
        for (Size i = 1; i < count; ++i) {
            *result++ = *++first;
        }
    }
    return result;
}

当您传递inscopy_n()时,该缓存1被复制到first参数中。copy_n()取消引用时first,它接收缓存1并输出到result. 然后copy_n()递增first读取2cin缓存它,然后取消引用first以接收2和输出它,然后递增first读取3cin缓存它,然后取消引用first以接收3和输出它,然后退出。

当你再次传递inscopy_n()时,原来的缓存1还在ins并被复制到first参数中。copy_n()取消引用时first,它接收缓存1并输出到result. 然后copy_n()递增first读取4cin缓存它,然后取消引用first以接收4和输出它,然后递增first读取5cin缓存它,然后取消引用first以接收5和输出它,然后退出。


推荐阅读