4.3. Операции сравнения и логические операции
Примечание. Все операции в результате дают значение типа bool Операции сравнения и логические операции в результате дают значение типа bool, то есть true или false. Если же такое выражение встречается в контексте, требующем целого значения, true преобразуется в 1, а false – в 0. Вот фрагмент кода, подсчитывающего количество элементов вектора, меньших некоторого заданного значения: vector<int>::iterator iter = ivec.beg-in() ; while ( iter != ivec.end() ) { // эквивалентно: e1em_cnt = e1em_cnt + (*iter < some_va1ue) // значение true/false выражения *iter < some_va1ue // превращается в 1 или 0 e1em_cnt += *iter < some_va1ue; ++iter; } Мы просто прибавляем результат операции “меньше” к счетчику. (Пара += обозначает
составной оператор присваивания, который складывает операнд, стоящий слева,
и операнд, стоящий справа. То же самое можно записать более компактно: elem_count
= elem_count + n. Мы рассмотрим такие операторы в разделе 4.4.) expr1 && expr2 expr1 || expr2 Если в первом из них expr1 равно false, значение всего выражения тоже будет
равным false вне зависимости от значения expr2, которое даже не будет вычисляться.
Во втором выражении expr2 не оценивается, если expr1 равно true, поскольку значение
всего выражения равно true вне зависимости от expr2. while ( ptr != О && ptr->va1ue < upperBound && ptr->va1ue >= 0 && notFound( ia[ ptr->va1ue ] )) { ... } Указатель с нулевым значением не указывает ни на какой объект, поэтому применение
к нулевому указателю операции доступа к члену вызвало бы ошибку (ptr->value).
Однако, если ptr равен 0, проверка на первом шаге прекращает дальнейшее вычисление
подвыражений. Аналогично на втором и третьем шагах проверяется попадание величины
ptr->value в нужный диапазон, и операция взятия индекса не применяется к
массиву ia, если этот индекс неправилен. bool found = false; // пока элемент не найден // и ptr указывает на объект (не 0) while ( ! found && ptr ) { found = 1ookup( *ptr ); ++ptr; } Подвыражение // Внимание! Порядок вычислений не определен! if ( ia[ index++ ] < ia[ index ] ) // поменять местами элементы Программист предполагал, что левый операнд оценивается первым и сравниваться будут элементы ia[0] и ia[1]. Однако компилятор не гарантирует вычислений слева направо, и в таком случае элемент ia[0] может быть сравнен сам с собой. Гораздо лучше написать более понятный и машинно-независимый код: if ( ia[ index ] < ia[ index+1 ] ) // поменять местами элементы ++index; Еще один пример возможной ошибки. Мы хотели убедиться, что все три величины ival, jval и kval различаются. Где мы промахнулись? // Внимание! это не сравнение 3 переменных друг с другом if ( ival != jva1 != kva1 ) // do something ... Значения 0, 1 и 0 дают в результате вычисления такого выражения true. Почему?
Сначала проверяется ival != jval, а потом итог этой проверки (true/false – преобразованной
к 1/0) сравнивается с kval. Мы должны были явно написать: Упражнение 4.4Найдите неправильные или непереносимые выражения, поясните. Как их можно изменить?
(Заметим, что типы объектов не играют роли в данных примерах.) Упражнение 4.5Язык С++ не диктует порядок вычисления операций сравнения для того, чтобы позволить компилятору делать это оптимальным образом. Как вы думаете, стоило бы в данном случае пожертвовать эффективностью, чтобы избежать ошибок, связанных с предположением о вычислении выражения слева направо? Назад ВпередСодержание |
Нет комментариев. Оставить комментарий: |