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