Инициализация istream_iterator cin ожидает ввода
У меня есть этот фрагмент кода. Объект istream_iterator только определен и не используется, поэтому я ожидаю, что он ничего не сделает и приложение завершит работу немедленно. Но когда я запускаю приложение, оно не завершится, пока я не предоставлю какой-либо ввод. Зачем?
Я собираю его на ArchLinux с помощью: gcc 4.7.1, с помощью команды: 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;
}
3 ответа
По стандарту,
24.6.1.1 Конструкторы и деструктор istream_iterator [istream.iterator.cons]
istream_iterator(istream_type& s);
3 - Эффекты: инициализирует в потоке с
&s
, значение может быть инициализировано во время построения или при первом обращении к нему.
Так что не определено, будет ли эта программа ждать ввода.
Тем не менее, трудно понять, как istream_iterator
может быть реализовано иначе; в соответствии с 24.6.1:1 после его создания [...] итератор считывает и сохраняет значениеT
, так что, если чтение не происходит на строительстве, то это должно произойти на operator *() const
и на свободе operator==(const istream_iterator<T> &, const istream_iterator<T> &)
, поэтому все внутреннее состояние итератора должно быть mutable
,
Предположительно, итератор istream немедленно вызовет cin >> x
извлечь первый токен и определить, должен ли он стать равным конечному итератору. Операция извлечения блокируется до тех пор, пока поток не будет закрыт, токен не извлечен или не будет обнаружен сбой анализа.
Обратите внимание, что заголовок вашего вопроса неверен: вы не только объявили input
, но вы также определили это. Если бы ваш код точно отражал вопрос, он бы сказал
extern istream_iterator<char> input; // declaration only!
и не было бы никакой блокировки.
Из потока вы можете "получить" каждое значение только один раз, после чего оно исчезнет. Однако общая потребность в итераторах состоит в том, чтобы обращаться к значению несколько раз без увеличения значения итератора. Таким образом, istream_iterator
извлечет первое значение в конструкции и скопирует его во внутреннее значение, которое затем возвращается при разыменовании итератора. Это также позволяет итератору определить, находится ли он в конце ввода, и стать конечным итератором. При увеличении читается следующее значение.
Попробуй это:
#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;
}