std :: istream_iterator<>与copy_n()和朋友 [英] std::istream_iterator<> with copy_n() and friends

查看:139
本文介绍了std :: istream_iterator<>与copy_n()和朋友的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面的代码段从 std :: cin 中读取三个整数;它将两个写入<$​​ c $ c>数字并舍弃第三个:

The snippet below reads three integers from std::cin; it writes two into numbers and discards the third:

std::vector<int> numbers(2);
copy_n(std::istream_iterator<int>(std::cin), 2, numbers.begin());

我希望代码从 std ::中读取两个整数cin ,但事实证明这是一个正确的,符合标准的行为。这是标准中的监督吗?

I'd expect the code to read exactly two integers from std::cin, but it turns out this is a correct, standard-conforming behaviour. Is this an oversight in the standard? What is the rationale for this behaviour?

从C ++ 03标准的24.5.1 / 1开始:

From 24.5.1/1 in the C++03 standard:


构造完成后,每个
time ++被使用,迭代器读取
并存储值 T

所以在上面的代码中,已读取一个整数。从这一点开始,迭代器在算法中的每次读取都是预读,产生从上一次读取中缓存的值。

So in the code above at the point of call the stream iterator already reads one integer. From that point onward every read by the iterator in the algorithm is a read-ahead, yielding the value cached from the previous read.

下一个标准的最新草案, n3225 ,此处似乎没有任何更改(24.6.1 / 1)

The latest draft of the next standard, n3225, doesn't seem to bear any change here (24.6.1/1).

在相关的注释中,当前标准的24.5.1.1/2引用 istream_iterator(istream_type& s)构造函数读取

On a related note, 24.5.1.1/2 of the current standard in reference to the istream_iterator(istream_type& s) constructor reads


效果:用
初始化 in_stream code> s 。 value 可以在
构建期间或第一次引用
时初始化。

Effects: Initializes in_stream with s. value may be initialized during construction or the first time it is referenced.

强调 value 可以初始化...,而不是强>初始化。这听起来与24.5.1 / 1矛盾,但也许应该有自己的问题。

With emphasis on "value may be initialized ..." as opposed to "shall be initialized". This sounds contradicting with 24.5.1/1, but maybe that deserves a question of its own.

推荐答案

未能在复制循环中考虑预读。 Visual C ++实现按照你期望的stringstream和std :: cin。我也检查了原始示例中istream_iterator是在行中构造的情况。

Unfortunately the implementer of copy_n has failed to account for the read ahead in the copy loop. The Visual C++ implementation works as you expect on both stringstream and std::cin. I also checked the case from the original example where the istream_iterator is constructed in line.

这是STL实现的关键代码片段。

Here is the key piece of code from the STL implementation.

template<class _InIt,
    class _Diff,
    class _OutIt> inline
    _OutIt _Copy_n(_InIt _First, _Diff _Count,
        _OutIt _Dest, input_iterator_tag)
    {   // copy [_First, _First + _Count) to [_Dest, ...), arbitrary input
    *_Dest = *_First;   // 0 < _Count has been guaranteed
    while (0 < --_Count)
        *++_Dest = *++_First;
    return (++_Dest);
    }

这里是测试代码

#include <iostream>
#include <istream>
#include <sstream>
#include <vector>
#include <iterator>

int _tmain(int argc, _TCHAR* argv[])
{
    std::stringstream ss;
    ss << 1 << ' ' << 2 << ' ' << 3 << ' ' << 4 << std::endl;
    ss.seekg(0);
    std::vector<int> numbers(2);
    std::istream_iterator<int> ii(ss);
    std::cout << *ii << std::endl;  // shows that read ahead happened.
    std::copy_n(ii, 2, numbers.begin());
    int i = 0;
    ss >> i;
    std::cout << numbers[0] << ' ' << numbers[1] << ' ' << i << std::endl;

    std::istream_iterator<int> ii2(std::cin);
    std::cout << *ii2 << std::endl;  // shows that read ahead happened.
    std::copy_n(ii2, 2, numbers.begin());
    std::cin >> i;
    std::cout << numbers[0] << ' ' << numbers[1] << ' ' << i << std::endl;

    return 0;
}


/* Output
1
1 2 3
4 5 6
4
4 5 6
*/

这篇关于std :: istream_iterator&lt;&gt;与copy_n()和朋友的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆