if (cin >> x) - Почему вы можете использовать это условие? - PullRequest
47 голосов
/ 22 июля 2011

Я использовал «Accelerated C ++» для изучения C ++ в течение лета, и есть концепция, которую я не совсем понимаю.

Почему

int x;
if (cin >> x){}

эквивалентно

cin >> x;
if (cin){}

Глядя на код, мне кажется, что мы используем cin как переменную. Но я думал, что это была функция. Почему мы можем использовать cin таким образом, когда x имеет значение, которое мы вводим в нашу клавиатуру?

Ответы [ 9 ]

59 голосов
/ 22 июля 2011

cin - это объект класса istream, представляющий стандартный поток ввода. Это соответствует cstdio потоку stdin. Оператор >> overload для потоков возвращает ссылку на тот же поток. Сам поток может быть оценен в булевом условии в true или false через оператор преобразования.

cin обеспечивает извлечение форматированного потока. Операция cin >> x;

, где "x" - это int, произойдет сбой, если нечисловое значение поступил. Итак:

if(cin>>x)

вернет false, если вы введете букву, а не цифру.

Этот веб-сайт, посвященный советам и рекомендациям по вводу / выводу C ++ , также поможет вам.

33 голосов
/ 22 июля 2011

Примечание: ответ обновляется через четыре года после факта, чтобы адресовать как C ++ 98/03, так и C ++ 11 (и более поздние версии).


std::cin является экземпляром std::istream. Этот класс обеспечивает две перегрузки, относящиеся к этому вопросу.

  • operator >> считывает данные из потока в целевую переменную, если это возможно. Если непосредственное содержимое потока не может быть преобразовано в тип целевой переменной, вместо этого поток помечается как недействительный, а целевая переменная остается нетронутой. Независимо от успеха / неудачи операции возвращаемое значение является ссылкой на поток.
  • Либо operator void*() (до C ++ 11), который преобразует ссылку на поток в указатель void*, либо explicit operator bool() (C ++ 11), который преобразует ссылку на поток в логическое значение. Результатом этого преобразования является ненулевой указатель (до C ++ 11) или true (C ++ 11), если поток действителен, но нулевой указатель (до C ++ 11) или false (C ++ 11), если поток недопустим.

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

Причина более запутанного элемента преобразования operator void* до C ++ 11 состоит в том, что только в C ++ 11 уже существующее ключевое слово explicit было расширено для применения к операторам преобразования, а также к конструкторам. , Неявный operator bool() предоставил бы программистам слишком много возможностей выстрелить себе в ногу. Также есть проблемы с operator void*(). «Безопасная идиома bool» была бы исправлением, но простое расширение explicit выполняло в точности то же, что и идиома безопасной bool, без необходимости использовать много магии SFINAE.

7 голосов
/ 22 июля 2011

cin - это (глобальная) переменная типа istream, а не функция.

Класс istream переопределяет оператор >>, чтобы выполнить ввод и вернуть ссылку на объект, который вы вызвали (cin).

6 голосов
/ 22 июля 2011

cin является переменной в std пространстве имен.

operator>> возвращает ссылку на cin, поэтому вы можете написать: cin >> a >> b вместо cin >> a; cin >> b;

4 голосов
/ 21 июня 2013

Ответы выше являются информативными. Здесь я просто даю дополнительный комментарий.

std::cin является объектом класса istream и представляет собой стандартный поток ввода (т.е. клавиатуру), который соответствует stdin в C stream .

cin >> x сначала прочитает int из стандартного входного потока и присвоит его x. После этого верните ссылку на себя cin. Таким образом, возвращаемое значение вызова функции cin >> x по-прежнему cin.

Таким образом, с точки , если условия , if(cin) и if(cin >> x) похожи друг на друга. Стандарт IO Library определяет функцию для потока следующим образом (зависит от реализации):

explicit operator bool() const; // C++11

или

operator void*() const; //C++98, C++2003

Из этих двух объявлений мы знаем, что они приводят тип потока прямо или косвенно (через void* pinter к bool, что очевидно) к bool типу.

В этих двух функциях они зависят от некоторых базовых IO steam статусов (полей классов), чтобы определить, возвращать ли false или true (для void*, это nullptr или нет).

cin является экземпляром класса istream, который наследует функцию casting-to-bool . Так работает!

4 голосов
/ 22 июля 2011

потому что результат выражения

cin >> x

оценивается как

cin

после чтения потока.

0 голосов
/ 17 апреля 2015

1) cin является экземпляром istream, см. http://www.cplusplus.com/reference/iostream/cin/.

2) оператор >> для istream вернет свой левый операнд, в данном случае это cin, см. http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/. Этот оператор установит failbit, если из символа не было извлечено cin, в случае, если читатель завершил EOF, поэтому больше не будет символов для чтения.

3) По состоянию на 2) выше, когда условие оценивается после операции чтения, if (cin >> x) должно быть похоже на if (cin), обратитесь к этой ссылке http://www.cplusplus.com/reference/ios/ios/operator_bool/, вы увидите, что это if блок вернется:

  • Нулевой указатель, если установлен хотя бы один из failbit или badbit. Иное значение (для стандарта C ++ 98).

  • Функция возвращает false, если хотя бы один из этих флагов ошибки установлен, и true в противном случае. (для стандарта C ++ 11)

0 голосов
/ 09 июля 2012

Как я знаю, перегруженный оператор >> возвращает объект класса istream. Вот почему здесь нет различий

0 голосов
/ 22 июля 2011

, поскольку cin является объектом класса, подробнее о http://www.cplusplus.com/reference/iostream/cin/.

...