If (cin >> x) - Почему вы можете использовать это условие?

Я использую "Ускоренный С++" для изучения С++ в течение лета, и есть концепция, которую я, похоже, не понимаю правильно.

Почему

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

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

cin >> x;
if (cin){}

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

Ответ 1

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

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

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

if(cin>>x)

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

Этот веб-сайт в подсказки и трюки с использованием ввода-вывода С++ также помогут вам.

Ответ 2

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


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

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

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

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

Ответ 3

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

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

Ответ 4

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

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

Ответ 5

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

cin >> x

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

cin

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

Ответ 6

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

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

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

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

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

или

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

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

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

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

Ответ 8

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

Ответ 9

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

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

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

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

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