<C++primer> 学习笔记【第四章】
目录
4.1基础概念
1.运算符的优先级、结合律和运算对象的求值顺序
2.左值和右值
定义
左值和右值的性质
4.2算术运算符
编辑
4.3逻辑和关系运算符
简述
逻辑运算符
关系运算符
4.4赋值运算符
4.5递增和递减运算符
4.6成员访问运算符
4.7条件运算符
单层条件运算符
嵌套条件运算符
注意事项
4.8 位运算符
编辑
左移运算符<<或右移运算符>>
位求反(~)、位与(&)、位或(|)、位异或(^)
位运算符的应用
移位运算符(重载IO运算符)的优先级和结合律
4.9 sizeof运算符
用法(2种)
优先级和结合律
运算符结果
4.10 逗号运算符
4.11类型转换
隐式转换
算术转换
数组(名)转换成指针
指针的转换
转换成布尔类型
转换成常量
显式转换(强制类型转换)
旧式
新式
4.12运算符优先级表
4.1基础概念
1.运算符的优先级、结合律和运算对象的求值顺序
优先级决定运算对象的组合方式
结合律决定运算顺序,左结合律即从左到右运算
求值顺序决定运算对象的求值顺序,只有逻辑和运算符(&&)、逻辑或运算符(||)、逗号运算符(,)、条件运算符(?)有求值顺序
&&先求左边的值,左边的值为真时才求右边的值,只有两个都是真才是真
||先求左边的值,左边的值为假时才求右边的值,只要有一个真就是真
括号无视优先级和结合律
典例
形如f()+f()g()+j()表达式,优先级决定f()g()最先运算,结合律决定f()与f()g()相加,再把结果与j()相加,求值顺序即f()、g()、j()谁先求值,若三者互有联系,则求值顺序不同会导致结果不同,无法通过编译,若无联系,则表达式成立
2.左值和右值
定义
左值指占有一定内存的对象,如变量,引用
右值指不占有内存的表达式,如常数,指针
int a=3; int 3=a;//错误
该式子中左值为a,右值为3
左值和右值的性质
1.赋值运算符左端为左值,得到的结果仍为左值
2.取地址符作用对象为左值,返回值为指针,即右值
3.解引用运算符、下标运算符运算对象为左值,求值结果为左值
4.内置类型和迭代器的递增递减运算符作用对象为左值,求值结果仍为左值
5.对于decltype,运算对象为左值时,返回类型为引用;运算对象为右值时,返回类型为右值
设p为int类型,解引用运算符生成左值,decltype(p)返回类型为int&
&p为右值,decltype(&p)返回类型为int,即指向整型指针的指针
4.2算术运算符
求商运算运算对象为整数,运算结果同号结果为正,异号结果为-,数值大小为绝对值相除,
返回值为整数,即去除小数部分
求余运算m%n,若结果不为0,则结果符号与m相同
即m%(-n)等于m%n,-m%n等于-(m%n)
4.3逻辑和关系运算符
简述
逻辑和关系运算符运算对象和返回值均为右值,且返回值均为布尔类型
布尔值可以隐式类型转换,转换为int类型,即0为false,非0为true
逻辑运算符
逻辑和运算符&&先求左边的值,左边的值为真时才求右边的值,只有两个都是真才是真
逻辑或运算符||先求左边的值,左边的值为假时才求右边的值,只要有一个真就是真
逻辑非运算符!运算对象的值取反后返回
关系运算符
有<,=,>,=,<=,>=,==,!=
4.4赋值运算符
1. 赋值运算符左侧运算对象必须是一个可修改的左值,运算结果是左侧运算对象,也为左值
若左右两个运算对象类型不同,则右侧运算对象转换为左侧运算对象的类型
可以用花括号括起来的初始值列表作为赋值语句的右侧运算对象,但最好保证左右类型相同
无论左侧运算对象类型是什么,右侧初始值列表可以为空
注意区分初始化和赋值的区别
2.算术运算符优先级高于关系运算符的优先级高于赋值运算符优先级
3.多重赋值中的每个对象,它的类型与右边对象的类型相同,或者能够由右边对象的类型转换得到
4.5递增和递减运算符
无论前置后置均作用于左值运算对象,包括迭代器
前置递增或递减运算符(++i为例),将加一后的对象本身作为左值返回
后置递增或递减运算符(i++为例),将对象加一,再把原始值的副本作为右值返回
注意除非必须,否则不用后置版本,因为会消耗不必要的内存
使用后置版本的情景时需要修改前的值
一般地,不要改变对象值的使用这个值,例如
beg=toupper(beg++);
产生歧义无法通过编译不知道左边的beg是加一前还是加一后的值
pbeg++等价于(pbeg++)
auto pbeg=v.begin(); hile(pbeg!=v.end()&&beg>=0) { cout<pbeg++等价于
cout<4.6成员访问运算符
ptr为指针,mem()为成员函数
ptr->mem()等价于(ptr).mem()
箭头运算符作用于指针,结果为左值
点运算符作用于对象,结果的类型根据对象的类型而定若对象为左值,结果也为左值,
若运算对象为右值,结果也为右值
可见箭头运算符更容易减少错误
解引用运算符优先级低于点运算符
ptr.mem()//错误,先执行ptr.mem(),但ptr为指针,没有成员函数
(ptr).mem()//正确,一定要加括号
4.7条件运算符
单层条件运算符
判断条件的表达式a?待输出的表达式b:待输出的表达式c
若a为真,计算b并输出b,若a为假,计算c并输出c
嵌套条件运算符
可在a或b、c处嵌套条件运算符,但建议最多嵌套到三层
string finalgrade=(grade>90)?"High grades":(grade<60)?"fail":"pass";注意事项
条件运算符优先级很低,善用括号
4.8 位运算符
知识引入
1.一个字节含有八个位,即八个格子容纳0或1,第一个格子称为第0位,一个格子称为第7位,具体怎么规定第一个格子和一个格子有两种不同角度,笔者暂且视作右边第一个格子为第0位,则第7位为符号位,正数为0,负数为1
2. 1UL为unsigned long类型的字面值1,UL为后缀
0UL 表示 无符号长整型 0 1UL 表示 无符号长整型 13.小整型会被提升至较大整型,一般为int类型(32位)
左移运算符<<或右移运算符>>
,n为非负整数
左移运算符x<
右移运算符n>>x表示对象x左侧插入n个值为0的二进制位
超出原有格子的部分除去
位求反(~)、位与(&)、位或(|)、位异或(^)
位求反(~)把每个位取反,比如00001100取反后为11110011
位与(&)一假全假,全真才真。(只要有一个是0,结果都是0,只有两个是1,才是1)
对1用位与(&)运算符,结果不变
即a和b相同的位上,
若a为0,b为1,则a&b在相同的位上值为0;
若a为1,b为1,则a&b在相同的位上值为1。
位或(|)一真全真,全假才假。(只要有一个是1,结果都是1,只有两个是0,才是0)
对0用位或(|)运算符,结果不变
位异或(^)相同为假,不同为真
&和|记忆方法和全x才x的对应的数字运算,结果不变
a:00000000 b:11111111 c:10011011 b&c:10011011 a|c:10011011位运算符的应用
情景一个班有30个学生,老师想用二进制的方法统计每个学生的考试通过情况
思路30个学生至少需要30个位,可知long至少有32个位,可以用long,每个位表示一个学生
的通过情况
#include#include using std::cout; using std::endl; using std::bitset; int main() { unsigned long quize1 = 0; quize1 |= (1uL<<27);//统计每个同学的考试通过情况,例如学号为27的同学通过考试,令第27位为1 cout << bitset<32>(quize1) << endl; quize1 &= (~quize1); cout << bitset<32>(quize1) << endl; } std::bitset<数字a>(变量名b)表示输出b的a个二进制位,使用时需要包含头文件bitset
移位运算符(重载IO运算符)的优先级和结合律
优先级算术运算符高于位运算符高于关系运算符、逻辑运算符、条件运算符,善用括号
结合律左结合律
4.9 sizeof运算符
用法(2种)
sizeof (类型)
sizeof 表达式 或 sizeof (表达式)
优先级和结合律
优先级高于加减乘除取余,高于关系运算符(除了逻辑非)和赋值运算符
低于递增递减运算符、函数调用运算符、成员选择运算符(点运算符和箭头运算符)
结合律右结合律
运算符结果
运算符结果取决于其作用的类型
1.对于char或类型为char的表达式,结果为1
2.对于引用,结果为被引用对象所占空间的大小
3.对于指针,结果为指针本身所占空间的大小
4.对于解引用指针,由于sizeof不计算表达式的值,指针可以无效,结果为指针指向的对象所占空间的大小
5.对于数组,不会把数组转化成指针,结果为整个数组所占空间的大小
数组元素个数等于sizeof(数组名)/sizeof(数组元素类型) 例如 int n[10]; //以下两条语句等价 int number=sizeof(n)/sizeof(int); int number = sizeof(n) / sizeof(n[2]);6.对于vector和string,只返回该类型固定部分的大小,不计算对象中的元素占用多少空间
7.对于成员函数,语句1和2等价(利用sizeof不计算表达式的值)
Sales_item item1; sizeof item1.mem();//语句1 sizeof Sales_item::mem();//语句24.10 逗号运算符
先对逗号左边表达式求值,然后丢弃结果,返回右边表达式求值后的值
逗号常用于for循环,末尾从结果的值上看等价于++ix,++t(执行一次循环后再执行该语句)
#include#include using std::cout; using std::endl; using std::vector; int main() { vector ivec(10, 2); vector ::size_type t = ivec.size(); for (vector ::size_type ix = 0; ix != ivec.size(); ix++, t--) { ivec[ix] = t; } for (auto c : ivec) { cout << c << " "; } } 4.11类型转换
运算符的运算对象需要同一类型,若不同类型,则需要转换成同一类型
隐式转换
算术转换
整型提升小整型(如char、signed char、unsigned char、short、unsigned short、bool)转换成大整型
(如int)
数组(名)转换成指针
指针的转换
任何非常量指针能够转换成void型
整数值0或字面值nullptr能够转换成任意指针类型,表示空指针
转换成布尔类型
如a为非布尔型变量,hile(a)、if(a)等等
转换成常量
非常量的指针或引用能够转换成常量的指针或引用
int i; const int &j=i; const intp=&i; int&r=j,q=p;//错误,常量指针或引用不能转换成非常量指针或引用显式转换(强制类型转换)
非必要尽量不使用强制类型转换
旧式
type (expression) 或 (type) expression 如 int i=2; double j=(double)i/0.2新式
格式cast-name
(expression) cast-name包括static_cast,const_cast和reinterpret_cast,一般只用前两者
static_cast除了更改底层const特性外都能执行强制类型转换
const_cast只能进行更改底层const特性,
注意若(指针或引用指向的)对象本身为常量,更改底层const特性后执行写操作容易出问题
若(指针或引用指向的)对象本身不是常量,更改底层const特性后执行写操作没问题
//例1 double d; void p=&d; doubledp =static_cast(p); //例2 const char pc; char p=const_cast (pc); 4.12运算符优先级表
空调维修
- 海信电视维修站 海信电视维修站点
- 格兰仕空调售后电话 格兰仕空调维修售后服务电
- 家电售后服务 家电售后服务流程
- 华扬太阳能维修 华扬太阳能维修收费标准表
- 三菱电机空调维修 三菱电机空调维修费用高吗
- 美的燃气灶维修 美的燃气灶维修收费标准明细
- 科龙空调售后服务 科龙空调售后服务网点
- 华帝热水器维修 华帝热水器维修常见故障
- 康泉热水器维修 康泉热水器维修故障
- 华凌冰箱维修电话 华凌冰箱维修点电话
- 海尔维修站 海尔维修站点地址在哪里
- 北京海信空调维修 北京海信空调售后服务
- 科龙空调维修 科龙空调维修故障
- 皇明太阳能售后 皇明太阳能售后维修点
- 海信冰箱售后服务 海信冰箱售后服务热线电话
- 海尔热水器服务热线