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. Так оно и работает!
Ответ 7
потому что cin является объектом класса, читайте больше на http://www.cplusplus.com/reference/iostream/cin/.
Ответ 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)