5.2. Relational and Logical Operators5.2. 关系操作符和逻辑操作符The relational and logical operators take operands of arithmetic or pointer type and return values of type bool. 关系操作符和逻辑操作符(表 5.2)使用算术或指针类型的操作数,并返回 bool 类型的值。 Table 5.2. Relational and Logical Operators表 5.2. 关系操作符和逻辑操作符Logical AND and OR Operators逻辑与、逻辑或操作符The logical operators treat their operands as conditions (Section 1.4.1, p. 12). The operand is evaluated; if the result is zero the condition is false, otherwise it is true. The overall result of the AND operator is TRue if and only if both its operands evaluate to TRue. The logical OR (||) operator evaluates to true if either of its operands evaluates to true. Given the forms 逻辑操作符将其操作数视为条件表达式(第 1.4.1 节):首先对操作数求值;若结果为 0,则条件为假(false),否则为真(true)。仅当逻辑与(&&)操作符的两个操作数都为 true,其结果才得 true 。对于逻辑或(||)操作符,只要两个操作数之一为 true,它的值就为 true。给定以下形式: expr1 && expr2 // logical AND expr1 || expr2 // logical OR expr2 is evaluated if and only if expr1 does not by itself determine the result. In other words, we're guaranteed that expr2 will be evaluated if and only if 仅当由 expr1 不能确定表达式的值时,才会求解 expr2。也就是说,当且仅当下列情况出现时,必须确保 expr2 是可以计算的:
A valuable use of the logical AND operator is to have expr1 evaluate to false in the presence of a boundary condition that would make the evaluation of expr2 dangerous. As an example, we might have a string that contains the characters in a sentence and we might want to make the first word in the sentence all uppercase. We could do so as follows: 对于逻辑与操作符,一个很有价值的用法是:如果某边界条件使 expr2 的计算变得危险,则应在该条件出现之前,先让 expr1 的计算结果为 false。例如,编写程序使用一个 string 类型的对象存储一个句子,然后将该句子的第一个单词的各字符全部变成大写,可如下实现: string s("Expressions in C++ are composed..."); string::iterator it = s.begin(); // convert first word in s to uppercase while (it != s.end() && !isspace(*it)) { *it = toupper(*it); // toupper covered in section 3.2.4 (p. 88) ++it; } In this case, we combine our two tests in the condition in the while. First we test whether it has reached the end of the string. If not, it refers to a character in s. Only if that test succeeds is the right-hand operand evaluated. We're guaranteed that it refers to an actual character before we test to see whether the character is a space or not. The loop ends either when a space is encountered or, if there are no spaces in s, when we reach the end of s. 在这个例子中,while 循环判断了两个条件。首先检查 it 是否已经到达 string 类型对象的结尾,如果不是,则 it 指向 s 中的一个字符。只有当该检验条件成立时,系统才会计算逻辑与操作符的右操作数,即在保证it确实指向一个真正的字符之后,才检查该字符是否为空格。如果遇到空格,或者 s 中没有空格而已经到达 s 的结尾时,循环结束。 Logical NOT Operator逻辑非操作符The logical NOT operator (!) treats its operand as a condition. It yields a result that has the opposite truth value from its operand. If the operand evaluates as nonzero, then ! returns false. For example, we might determine that a vector has elements by applying the logical NOT operator to the value returned by empty: 逻辑非操作符(!)将其操作数视为条件表达式,产生与其操作数值相反的条件值。如果其操作数为非零值,则做 ! 操作后的结果为 false。例如,可如下在 vector 类型对象的 empty 成员函数上使用逻辑非操作符,根据函数返回值判断该对象是否为空: // assign value of first element in vec to x if there is one int x = 0; if (!vec.empty()) x = *vec.begin(); The subexpression 如果调用 empty 函数返回 false,则子表达式 !vec.empty() evaluates to true if the call to empty returns false. 的值为 true。 The Relational Operators Do Not Chain Together不应该串接使用关系操作符The relational operators (<, <=, >, <=) are left associative. The fact that they are left associative is rarely of any use because the relational operators return bool results. If we do chain these operators together, the result is likely to be surprising: 关系操作符(<、<=、>、<=)具有左结合特性。事实上,由于关系操作符返回bool类型的结果,因此很少使用其左结合特性。如果把多个关系操作符串接起来使用,结果往往出乎预料:
// oops! this condition does not determine if the 3 values are unequal
if (i < j < k) { /* ... */ }
As written, this expression will evaluate as true if k is greater than one! The reason is that the left operand of the second less-than operator is the TRue/ false result of the firstthat is, the condition compares k to the integer values of 0 or 1. To accomplish the test we intended, we must rewrite the expression as follows: 这种写法只要 k 大于 1,上述表达式的值就为 true。这是因为第二个小于操作符的左操作数是第一个小于操作符的结果:true 或 false。也就是,该条件将 k 与整数 0 或 1 做比较。为了实现我们想要的条件检验,应重写上述表达式如下: if (i < j && j < k) { /* ... */ } Equality Tests and the bool Literals相等测试与 bool 字面值As we'll see in Section 5.12.2 (p. 180) a bool can be converted to any arithmetic typethe bool value false converts to zero and true converts to one. 正如第 5.12.2 节将介绍的,bool 类型可转换为任何算术类型——bool 值 false 用 0 表示,而 true 则为 1。
if (val == true) { /* ... */ } Either val is itself a bool or it is a type to which a bool can be converted. If val is a bool, then this test is equivalent to writing val 本身是 bool 类型,或者 val 具有可转换为 bool 类型的数据类型。如果 val 是 bool 类型,则该判断条件等效于: if (val) { /* ... */ } which is shorter and more direct (although admittedly when first learning the language this kind of abbreviation can be perplexing). 这样的代码更短而且更直接(尽管对初学者来说,这样的缩写可能会令人费解)。 More importantly, if val is not a bool, then comparing val with true is equivalent to writing 更重要的是,如果 val 不是 bool 值,val 和 true 的比较等效于: if (val == 1) { /* ... */ } which is very different from 这与下面的条件判断完全不同: // condition succeeds if val is any nonzero value if (val) { /* ... */ } in which any nonzero value in val is true. If we write the comparison explicitly, then we are saying that the condition will succeed only for the specific value 1. 此时,只要 val 为任意非零值,条件判断都得 true。如果显式地书写条件比较,则只有当 val 等于指定的 1 值时,条件才成立。 ![]() |