《C++ Primer》读书笔记第四章-1-基础 And 运算符

来源:互联网 发布:树莓派的编程语言 编辑:程序博客网 时间:2024/06/05 01:00

笔记会持续更新,有错误的地方欢迎指正,谢谢!

前言:
1. C++ 提供了一套丰富的运算符,可以用于内置类型对象的操作。即便运算对象是自定义的类类型,C++也允许程序员指定这些运算符的含义(真的给了程序员很大的自由和挑战,第十四章才讲这个,等着吧23333)。
2. 本章主要介绍用于内置类型运算对象的运算符,简单介绍几种标准库定义的运算符。

基础

基本概念

C++定义了两个概念:
一元运算符:作用于一个运算对象,如取地址符&。
二元运算符:作用于两个运算对象,如乘法运算符,一些符号两种都行,比如*作为乘法是二元,作为解引用是一元。

左值右值

  1. C++的表达式要么是左值,要么就是右值;
  2. 当一个对象被用作右值的时候,用的是对象的值(所含的内容);当对象被用作左值的时候,用的是对象的身份(内容在内存中的地址)。

求值顺序

例1:
int i = f1() * f2();
我们不知道f1和f2哪个先调用
例2:
int i = 0;
cout << i << " " << ++i << endl;
cout << ++i << " " << i << endl;
都输出:1 1

黄金法则:不确定的时候用括号啊~

运算符

算术运算符

特殊1:
bool b = true;
bool b2 = -b //b2还是true,因为-b=-1,只要非零都是true,所以不要用布尔值参与计算。

特殊2:
int a = b % pi; //报错,必须对整型求余。
求余还有些注意的地方: m%(-n) = m%n; (-m)%n = -(m%n) 简单来说,就是n的符号省略,m的符号放括号外面。

逻辑和关系运算符

逻辑运算符:

逻辑运算符 功能 ! 逻辑非 && 逻辑与 || 逻辑或

&&和||都是短路求值,比如求a&&b,如果a为假,编译器就不会去判断b的真假。

关系运算符:
因为关系运算符的求值结果是布尔值,所以将几个关系运算符连写在一起会产生意向不到的错误结果:

int i = 0, j = 5, k = 2;if(i<j<k) //错误写法,这里为真。因为i<j为真,值为1,又1<k。if(i<j && j<k) //正确写法,这里为假。

另外,再强调一遍,true的值:
例子:
if(val) //只要val不是零,都是true。

赋值运算符

易混淆题型:
int i = 0, j = 0, k = 0;
k = {3.14}; //错误:因为列表初始化不允许损失精度。
i = j = 1; //正确:i和j都被赋值为1。
int ival, *pval;
ival = pval = 0; //错误:不能把指针的值赋值给int。(地址是一种标识,而这种标识和整数没有关系。不能因为地址看起来像数字就认为它是整型。)

递增和递减运算符

我们推荐++i,因为++i将对象本身作为左值(内容在内存中的地址)返回,节省资源,i++则将对象原始值的副本作为右值(内容)返回。即左值可代替右值的一种体现:左值根据地址去获得右值的内容进行+1,但它还是左值!

递增运算符和解引用同时存在:
cout << *beg++ << endl; //按照优先级先解引用,再+1。

成员访问运算符

点运算符、箭头运算符都可用于访问成员,如下:

string s = "hi", *p = &s;//以下三个n等价:auto n1 = s.size();//点运算符的应用。另外,容器的性质string基本都有。auto n2 = (*p).size(); //点运算符的应用。括号不能少哦,因为解引用的优先级低!auto n3 = p->size();//箭头运算符的应用。

条件运算符

唯一的一个三目运算符。
string res = grade < 60 ? “abc” : “def”;

位运算符

作用于整型类型的运算对象,并把对象看成是二进制。

运算符 功能 ~ 求反 << 左移 >> 右移 & 位与:都为1才为1 | 位或:一个为1就是1 ^ 位亦或:不同才为1

移位运算符

  1. a << 3;)左移运算符<<在右侧插入值为0的二进制位;
  2. a >> 3;)右移运算符>>的行为依赖于运算对象的类型,如果运算对象是无符号类型,左侧插入0即可,如果是带符号类型,正数用0填补,负数用1填补。注:不同的环境填补方式可能不同。

使用位运算符:超级省内存空间!(应多用位运算符!)

unsigned long quiz = 0; //初始化,全班都没过,用long是为了至少有32位。//题目1:怎么记录27号(编号从0开始)学生通过了?//解答:设value是unsigned long的1,然后左移27位(从第0位开始的,第0位在最右边),1就到第27位来了。quiz = quiz | (value<< 27)//(value<< 27)的值并未保存到value中。//题目2:假设后来检查的时候发现27号挂科了,那怎么修改呢?quiz &= ~(value<< 27);//quiz 只有27号学生的成绩,并且只有通过位与运算解决之。//查看27号有没有过?bool status = quiz & (value<< 27);

sizeof运算符

它只根据类型返回一条表达式或一个类型名称所占的字节数。
例子:

Book *book;//book是指向Book类型对象的指针。sizeof *p;//p所指类型的空间大小,即sizeof(Book)。

运算符优先级表

在P147,我的建议是:用到的时候去查,反正你也记不住这么多,实在不行就用括号呗。

原创粉丝点击