std :: istream_iterator<>与copy_n()和朋友 [英] std::istream_iterator<> with copy_n() and friends
问题描述
下面的代码段从 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
withs
.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<>与copy_n()和朋友的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!