Question

I've got this code snippet. The istream_iterator object is only defined and not used, so I expect that it won't do anything and application finish immediately. But when I run application, it will not finish before I provide some input. Why?

I'm compiling it on ArchLinux with: gcc 4.7.1, with command: g++ -std=c++11 filename.cpp

#include <iterator>
#include <iostream>

using namespace std;

int main(int argc, char *argv[])
{
    istream_iterator<char> input(cin);

    return 0;
}
Was it helpful?

Solution

Per the standard,

24.6.1.1 istream_iterator constructors and destructor [istream.iterator.cons]

istream_iterator(istream_type& s);

3 - Effects: Initializes in-stream with &s. value may be initialized during construction or the first time it is referenced.

So it is unspecified whether this program will wait for input.

However, it's difficult to see how istream_iterator could be implemented otherwise; per 24.6.1:1, after it is constructed [...] the iterator reads and stores a value of T, so if the read does not occur on construction then it would need to occur on operator *() const and on the free operator==(const istream_iterator<T> &, const istream_iterator<T> &), so all of the internal state of the iterator would have to be mutable.

OTHER TIPS

Presumably, the istream iterator will immediately call cin >> x to extract the first token and determine whether it should become equal to the end iterator. The extraction operation blocks until either the stream is closed, a token is extracted or a parsing failure is encountered.

Note that your question title is wrong: You have not only declared input, but you have also defined it. If your code were to reflect the question accurately, it would say

extern istream_iterator<char> input;  // declaration only!

and there would be no blockage.

From a stream, you can only "get" every value once, after that it's gone. However, a common need for iterators is to access a value multiple times without incrementing the iterator. As such, the istream_iterator will extract the first value on construction and copy it into an internal value which is then returned when dereferencing the iterator. This also allows the iterator to determine whether it's at the end of input and become an end iterator. On incrementing, the next value is then read.

Try this:

#include <iostream>
#include <iterator>

using namespace std;

int main()
{
    istream_iterator<int> start(cin);
    istream_iterator<int> itend;

    while( start != itend ) {
        cout << *start << endl;
        start++;
        //Press Enter followed by Control-D on linux to exit the loop
    }

    cout<<"Control-D Pressed "<<endl;
    return 0;
}

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top