专栏简介:本专栏主要面向C++初学者,解释C++的一些基本概念和基础语言特性,涉及C++标准库的用法,面向对象特性,泛型特性高级用法。通过使用标准库中定义的抽象设施,使你更加适应高级程序设计技术。希望对读者有帮助!
目录
- 4.3逻辑和关系运算符
- 逻辑与和逻辑或运算符
- 逻辑非运算符
- 关系运算符
4.3逻辑和关系运算符
关系运算符作用于算术类型或指针类型,逻辑运算符作用于任意能转换成布尔值的类型。逻辑运算符和关系运算符的返回值都是布尔类型。值为0的运算对象(算术类型或指
针类型)表示假,否则表示真。对于这两类运算符来说,运算对象和求值结果都是右值。
表4.2:逻辑运算符和关系运算符
结合律 | 运算符 | 功能 | 用法 |
---|---|---|---|
右 | ! | 逻辑非 | !expr |
左 | < | 小于 | expr < exp |
左 | <= | 小于等于 | expr <= exp |
左 | > | 大于 | expr > expr |
左 | >= | 大于等于 | expr >= expr |
左 | == | 相等 | expr==expr |
左 | != | 不相等 | expr != expr |
左 | && | 逻辑与 | expr && expr |
左 | || | 逻辑或 | expr || expr |
逻辑与和逻辑或运算符
对于逻辑与运算符(&&)来说,当且仅当两个运算对象都为真时结果为真;对于逻辑或运算符(||)来说,只要两个运算对象中的一个为真结果就为真。
逻辑与运算符和逻辑或运算符都是先求左侧运算对象的值再求右侧运算对象的值,当且仅当左侧运算对象无法确定表达式的结果时才会计算右侧运算对象的值。这种策略称为短路求值(short circuit evaluation)。
- 对于逻辑与运算符来说,当且仅当左侧运算对象为真时才对右侧运算对象求值。
- 对于逻辑或运算符来说,当且仅当左侧运算对象为假时才对右侧运算对象求值。
举一个使用逻辑或运算符的例子,假定有一个存储着若干string对象的vector对象,要求输出string对象的内容并且在遇到空字符串或者以句号结束的字符串时进行换行。使用基于范围的for循环处理string对象中的每个元素:
// s是对常量的引用;元素既没有被拷贝也不会被改变
for(const auto &s:text){ // 对于text的每一个元素
cout<<s;// 输出当前元素
//遇到空字符争或者以句号结束的字符串进行换行
if(s.empty() || s[s.stze()-1]==‘.’)
cout<<endl;
else
cout<<““;//否则用空格隔开
}
输出当前元素后检查是否需要换行。if语句的条件部分首先检查s是否是一个string,如果是,则不论右侧运算对象的值如何都应该换行。只有当string对象非空时才需要求第二个运算对象的值,也就是检查string对象是否是以句号结束的。在这条表达式中,利用逻辑或运算符的短路求值策略确保只有当s非空时才会用下标运算符去访间它。值得注意的是,s被声明成了对常量的引用。因为text的元素是string对象,可能非常大,所以将s声明成引用类型可以避免对元素的拷贝;又因为不需要对string对象做写操作,所以s被声明成对常量的引用。
逻辑非运算符
逻辑非运算符(!)将运算对象的值取反后返回,之前我们曾经使用过这个运算符。下面再举一个例子,假设vec是一个整数类型的vector对象,可以使用逻辑非运算符将empty函数的返回值取反从而检查vec是否含有元素:
//输出vec的首元素(如果有的话)
if(vec.empty())
cout<<vec[0];
子表达式
!vec.empty.()
当empty函数返回假时结果为真。
关系运算符
顾名思义,关系运算符比较运算对象的大小关系并返回布尔值。关系运算符都满足左结合律。
因为关系运算符的求值结果是布尔值,所以将几个关系运算符连写在一起会产生意想不到的结果:
//错误!这个条件居然拿i<j的布尔值结果和k比较!
if(i<j<k) //若K大于1则为真!
if语句的条件部分首先把i、j和第一个<运算符组合在一起,其返回的布尔值再作为第二个<运算符的左侧运算对象。也就是说,k比较的对象是第一次比较得到的那个或真或假的结果!要想实现我们的目的,其实应该使用下面的表达式:
//正确;当i小j并小于k时条件为真
if(i < j && j< k) {/**/}
## 相等性测试与布尔字面值
如果想测试一个算术对象或指针对象的真值,最直接的方法就是将其作为if语句的条件:
```cpp
if(val){/*...*/} //如果val是任意的非0值,条件为真
if(!val){/*...*/} //如果val是0,条件为真
在上面的两个条件中,编译器都将val转换成布尔值。如果val非0则第一个条件为真,如果val的值为0则第二个条件为真。
有时会试图将上面的真值测试写成如下形式:
if(val==true){/*…*/}//只有当val等于1时条件才为真!
但是这种写法存在两个问题:首先,与之前的代码相比,上面这种写法较长而且不太直接(尽管大家都认为缩写的形式对初学者来说有点难理解);更重要的一点是,如果val不是布尔值,这样的比较就失去了原来的意义。
如果val不是布尔值,那么进行比较之前会首先把true转换成val的类型。也就是说,如果val不是布尔值,则代码可以改写成如下形式:
if(val==1){/* ... */}
正如我们已经非常熟悉的那样,当布尔值转换成其他算术类型时,false转换成0而true转换成1。如果真想知道val的值是否是1,应该直接写出1这个数值来,而不要与true比较。