【C++基础】第二十二课:逻辑和关系运算符

逻辑运算符,关系运算符

Posted by x-jeff on March 6, 2021

【C++基础】系列博客为参考《C++ Primer中文版(第5版)》C++11标准)一书,自己所做的读书笔记。
本文为原创文章,未经本人允许,禁止转载。转载请注明出处。

1.前言

  • 关系运算符作用于算术类型或指针类型。
  • 逻辑运算符作用于任意能转换成布尔值的类型。

指针比较大小:可以使用C++的任何关系运算符来比较指针,包括><==!=>=<=

如果内存中的一个地址在另一个地址之前,则第一个地址被认为是“小于”第二个地址。在一个数组中,所有元素都存储在连续的内存位置,所以元素[1]的地址大于元素[0]的地址,如下图所示:

逻辑运算符和关系运算符的返回值都是布尔类型。值为0的运算对象(算术类型或指针类型)表示假,否则表示真。对于这两类运算符来说,运算对象和求值结果都是右值。

2.逻辑与和逻辑或运算符

  • 对于逻辑与运算符(&&)来说,当且仅当两个运算对象都为真时结果为真。
  • 对于逻辑或运算符(||)来说,只要两个运算对象中的一个为真结果就为真。

👉逻辑与运算符和逻辑或运算符都是先求左侧运算对象的值再求右侧运算对象的值,当且仅当左侧运算对象无法确定表达式的结果时才会计算右侧运算对象的值。这种策略称为短路求值(short-circuit evaluation)

  • 对于逻辑与运算符来说,当且仅当左侧运算对象为真时才对右侧运算对象求值。
  • 对于逻辑或运算符来说,当且仅当左侧运算对象为假时才对右侧运算对象求值。

举个逻辑或的例子,假定有一个存储着若干string对象的vector对象,要求输出string对象的内容并且在遇到空字符串或者以句号结束的字符串时进行换行:

1
2
3
4
5
6
7
8
//s是对常量的引用;元素既没有被拷贝也不会被改变
for(const auto &s : text){
	cout<<s;
	if(s.empty() || s[s.size()-1]=='.')
		cout<<endl;
	else
		cout<<" ";
}

只有当string对象非空时才需要求第二个运算对象的值,也就是检查string对象是否是以句号结束的。

⚠️值得注意的是,s被声明成了对常量的引用。因为text的元素是string对象,可能非常大,所以将s声明成引用类型可以避免对元素的拷贝;又因为不需要对string对象做写操作,所以s被声明成对常量的引用。

3.逻辑非运算符

逻辑非运算符(!)将运算对象的值取反后返回。

4.关系运算符

顾名思义,关系运算符比较运算对象的大小关系并返回布尔值。

如果我们想判断当i小于j并且j小于k时条件为真,不能写成:

1
if(i<j<k)//若k大于1则为真!

该if语句的条件部分首先把i、j和第一个<运算符组合在一起,其返回的布尔值再作为第二个<运算符的左侧运算对象。正确写法应该为:

1
if(i<j && j<k)

5.相等性测试与布尔字面值

如果想测试一个算术对象或指针对象的真值,最直接的方法就是将其作为if语句的条件:

1
2
if(val) { /*...*/ } //如果val是任意的非0值,条件为真
if(!val) { /*...*/ } //如果val是0,条件为真

其并不等价于下述判断:

1
if(val==true) { /*...*/ } //只有当val等于1时条件才为真!

如果val不是布尔值,那么进行比较之前会首先把true转换成val的类型。例如上述代码可以改写成如下形式:

1
if(val==1) { /*...*/ }

⚠️进行比较运算时除非比较的对象是布尔类型,否则不要使用布尔字面值true和false作为运算对象。

6.参考资料

  1. C++指针比较大小(详解版)