c++primer 学习笔记 第四章

第四章 表达式

表达式由一个或多个运算对象组成,对表达式求值将得到一个结果。

1.基础

1.基本概念

一元运算符:作用于一个运算对象。如取址符和解引用符。

二元运算符:作用于两个运算对象。如==,<这些

函数调用也是特殊的运算符,对运算对象的数量没有限制。

重载运算符:IO库的<<,>>以及string对象,vector对象,迭代器使用的运算符都是重载的运算符。

2.求值顺序,优先级,结合律

可以利用括号改变运算顺序。

对于未指定运算顺序的运算符,如int i=f()*f1(),我么不知道是先调用f还是f1。

这样的情况如果表达式指向并修改了同一个对象,将会产生错误。

cout<<i<<++i<<endl; //未定义的

&&,||,?:,和逗号,运算符指定了顺序

2.算术运算符

注意,大多数运算符会把布尔类型提升为int类型。

bool b=true; //运算时被提升为整数值1

bool b2=-b; //-b是-1,将-1转换为布尔值作为b2的初始,初始值不为0,转换为布尔值是1,所以b2值为真。(p33类型转换,其他值转换为布尔类型,值为0则为false,否则为true

整数相除还是整数,直接舍弃小数。

%的运算对象必须是整数。

m, n是整数且n不为0,则**(m/n)*n+m%n=m。**m%n的符号与m相同。

3.逻辑和关系运算符

返回值都是布尔类型。

&&和||都是先对左侧求值再求右侧,&&当且仅当左侧为真才求右侧,||当且仅当左侧为假才求右侧。

if(i<j<k)其实是用i<j的布尔值和k作比较,显然不对,应该用逻辑与运算符写两个。

如果想测试一个算数运算对象或者指针对象的真值:

if(val) { } //val是任意非0值,条件为真

if(val==true) {} //如果val不是布尔值,比较前会将true转换为1,就变成了if(val==1)写法错误

4.赋值运算符

赋值运算符优先级较低,再条件语句中应该加括号。

5.递增和递减运算符

++和–不仅书写简单,还可以应用于迭代器例如*pebg++。

前置版本:++i,先把运算对象加一,将改变后的对象作为结果,将对象本身作为左值返回

后置版本:i++,加一后的值作为运算对象改变前的值的副本,将对象原始值的副本作为右值返回

int i=0,j;

j=++i; //j=1,i=1

j=i++; //j=1,i=2

尽量使用前置,因为后置需要储存原始值,对于复杂的迭代器类型消耗太大了。

6.成员访问运算符

点运算符和箭头运算符都可访问成员,ptr->mem等价于(*ptr).men。解引用优先级低于点运算符。

7.条件运算符(?:)

cond?expr1:expr2

cond为真对expr1求值并返回,否则对expr2求值

可以嵌套

a=(grade>90)?"high pass"

:(grade<60)?"fail":"pass"

输出表达式使用条件运算符,记得加最外层的括号

cout<<((grade<60)?"fail":"pass");

8.位运算符

**建议仅将位运算符用于处理无符号类型。**因为位运算符如何处理运算对象的符号位依赖于机器,而且左移操作可能改变符号位位置。

移位运算符:左移<<右移>>

求反运算符:~

位与&,位或|,异或^

9.sizeof运算符

sizeof返回一个表达式或者一个类型名字所占的字节数。所得的值是一个size_t类型的常量表达式。

**sizeof并不会实际计算其运算对象的值,**所以再sizeof运算对象中解引用一个无效指针依然安全。如sizeof *p。

sizeof(引用类型)得到被引用对象所占空间大小。

sizeof(指针)得到指针本身所占空间大小。

sizeof(解引用指针)得到指针指向的对象所占空间大小,指针不需要有效。

sizeof(数组)得到数组所占空间大小,注意不会将数组转换为指针处理。数组大小/单个元素大小=数组元素个数,constexpr size_t size=sizeof(arr)/sizeof(*arr)

sizeof(vector/string对象)只返回该类型固定部分的大小,不会计算对象中的元素占了多少空间。

10.类型转换

1.算术转换

运算符的运算对象会转换成最宽的类型。

整型提升:小整数类型转换为大整数类型。(例如bool, signed char, unsigned char, char, short,unsigned short会被提升为int)

2.其它隐式类型转换

数组自动转换成指向数组首元素的指针,数组被用作decltype关键字参数,或者取址符,sizeof,typeid等运算符的运算对象时,上述转换不会发生。同时用引用初始化数组时也不会发生

算术类型或指针类型自动转换为布尔类型。

指向非常量的指针转换为指向相应常量类型的指针,引用也是。

3.显式转换

强制类型转换:cast_name <目标类型> (表达式)

static_cast:只要不包含底层const就可以

void* p=&d; //任何非常量对象的地址都可以存入void *

double *dp=static_cast<double*>(p); //将void* 类型转换为初始指针类型

**const_cast:**去const性质

reinterpret_cast

旧式类型转换:(目标转换类型)表达式

**尽量避免强制类型转换。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值