Изменение поведения istream в C++ при сбое
Взять из: cppreference
До C++11:
Если извлечение завершается неудачно (например, если буква была введена там, где ожидается цифра), значение остается неизменным, и бит сбоя устанавливается.
Начиная с C++11:
Если извлечение завершается неудачно, в значение записывается ноль, и бит сбоя устанавливается. Если извлечение приводит к значению, слишком большому или слишком маленькому, чтобы соответствовать значению,
std::numeric_limits<T>::max()
или жеstd::numeric_limits<T>::min()
написано и флаг сбоя установлен.
Из-за этого изменения это означает, что следующий фрагмент:
int x = 1;
std::cin >> x;
return x;
в случае сбоя числового преобразования вернется 1
до C++ 11 и 0
иначе.
Зачем комитет по стандартизации вводит такие тонкие изменения? Или, скорее, какой код был возможен до C++ 11, который гарантировал это изменение?
2 ответа
Кажется, как и было указано, operator>>
s были сломаны в некоторых случаях (то есть, строго говоря, не могло существовать). Это "исправить".
В проекте с начала 2011 года Стандарт в основном такой же, как и в 2003 году. Однако в отчете о дефектах библиотеки, открытом Мэттом Остерном (в 1998 году!), num_get<>::get()
не существует для short
а также int
, Таким образом, они были изменены, чтобы использовать long
версия, и проверьте, что прочитанное число попадает в правильный диапазон.
Отчет о дефектах находится здесь.
(На самом деле не объясняется, почему они не думали, что могут сохранить изначально намеченное поведение, но именно поэтому эта часть стандарта была изменена.)
Это больше C++ способ делать вещи, чтобы хранить ноль в неconst
эталонный вход x
затем возвращая исходное значение в случае ошибки.
Чтобы сохранить исходное значение в случае возникновения ошибки, библиотека должна работать с временным. Он не может просто использовать пространство, предоставленное x
без сохранения исходного значения где-то. Тогда это может также сделать копию x
в какой-то момент, когда условия ошибки известны. Как иначе вы бы получили исходное значение, если есть ошибка или чтение ввода в противном случае. Таким образом, каждый платит цену, независимо от того, хотят они этого поведения или нет.
Таким образом, возвращение исходного значения в случае ошибки вовсе не является C++. Если вы хотите такое поведение, просто заплатите за него сами - создайте временный и передайте егоconst
ссылка на operator>>
, что-то вроде:
int x = 1;
int temp;
if (std::cin >> temp)
x = temp;
return x;