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;
}

person Robert Balent    schedule 26.09.2012    source источник
comment
Ничего общего с C ++ 11, поэтому я удалил этот тег.   -  person Xeo    schedule 26.09.2012


Ответы (4)


Согласно стандарту,

24.6.1.1 конструкторы и деструктор istream_iterator [istream.iterator.cons]

istream_iterator(istream_type& s);

3 - Эффекты: инициализирует in-stream с &s. value может быть инициализировано во время построения или при первой ссылке на него.

Таким образом, не указано, будет ли эта программа ждать ввода.

Однако трудно понять, как istream_iterator можно было бы реализовать иначе; согласно 24.6.1: 1, после создания [...] итератор считывает и сохраняет значение T, поэтому, если чтение не происходит при построении, это должно произойти на operator *() const и на свободном operator==(const istream_iterator<T> &, const istream_iterator<T> &), поэтому все внутреннее состояние итератора должно быть mutable.

person ecatmur    schedule 26.09.2012

Предположительно, итератор istream немедленно вызовет cin >> x, чтобы извлечь первый токен и определить, должен ли он стать равным конечному итератору. Операция извлечения блокируется до тех пор, пока поток не будет закрыт, не будет извлечен токен или не произойдет сбой синтаксического анализа.

Обратите внимание, что заголовок вашего вопроса неправильный: вы не только объявили input, но также определили его. Если бы ваш код точно отражал вопрос, он бы сказал

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

и не было бы завалов.

person Kerrek SB    schedule 26.09.2012
comment
@BoBTFish: Конечно. Если вы думаете об этом, нет никакого способа обойти это, поскольку вы должны знать, достигли ли вы конца: input == istream_iterator<char>() должен дать правильный ответ. - person Kerrek SB; 26.09.2012
comment
Все определения также являются декларациями (но не наоборот). Я бы не сказал, что название было неправильным. - person Joseph Mansfield; 26.09.2012
comment
@sftrabbit: Конечно, но просто чтобы быть педантичным, блокирует не объявление (что было бы странно, потому что объявление - это всего лишь часть грамматики), а определение (которое является фактическим исполняемым кодом). Это все равно, что задать вопрос Ошибка выше main(). Верно, но не очень конкретно. - person Kerrek SB; 26.09.2012
comment
@sftrabbit, вы оба ошибаетесь; это инициализация, которая блокирует. Я исправил заголовок и прояснил вопрос (надеюсь, не изменив намерения). - person ecatmur; 26.09.2012
comment
@ecatmur: Да, конечно, но определение влечет за собой инициализацию! :-) - person Kerrek SB; 26.09.2012
comment
@ecatmur Полагаю, я интерпретировал это как объявление в своих блоках примеров кода, которое является истинным. Хотя в общем смысле я согласен. - person Joseph Mansfield; 26.09.2012

Из потока вы можете «получить» каждое значение только один раз, после чего оно исчезнет. Однако общая потребность в итераторах - многократный доступ к значению без увеличения итератора. Таким образом, istream_iterator будет извлекать первое значение при построении и копировать его во внутреннее значение, которое затем возвращается при разыменовании итератора. Это также позволяет итератору определить, находится ли он в конце ввода и становится ли он конечным итератором. При увеличении считывается следующее значение.

person Xeo    schedule 26.09.2012

Попробуй это:

#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;
}

person Anoop Kumar Narayanan    schedule 22.10.2019
comment
Просто помните, что он закрывает входной поток. - person Anoop Kumar Narayanan; 22.10.2019