【c++primer第五版】第四章-基础知识--表达式(运算符)

目录

 

基础:

算数运算符

逻辑和关系运算符

条件运算符

位运算符

sizeof()运算符

逗号运算符

类型转换

算数转换:

其他隐式类型转换


基础:

一元运算符和二元运算符

作用于一个对象的是一元运算符,(解引用*,&)作用于两个对象的是二元运算符(*,==);

运算的过程中,运算对象可以由一种类型转换为另一种类型;

重载运算符:当运算符所用与类类型的运算对象时,用户可以自定义其含义,这种自定义的过程是为已存在的运算符赋予另外一层含义,叫做~;比如:<<;>>;string对象,vector对象使用的运算符;

括号无视优先级和结合律;

int ia[] = {0,2,3,4,5,6};
int last = *(ia + 4);    last 初始化为ia[4];
cin >> v1 >> v2;    先读入v1,之后v2;
优先级规定了运算对象的组合方式,但是没有运算对象按照什么方式求值
int i = f1 * f2;    不知道是先调用f1 还是先调用f2
有4种运算符明确规定了运算对象的求值顺序
&&--先求左侧运算值,左侧为真时继续求右侧
||--先求左侧运算对象的值,左侧为假时,对右侧对象取值
(,)逗号运算符--
条件运算符--
注意:一般地,处理符合表达式时,可以用括号来强制规定优先级;
      一般地,如果改变可某个运算对象的值,在表达式的其他地方不要再使用这个运算对象;

算数运算符

+    一元正号
-    一元负号
一元运算符优先级最高,之后是乘法和除法,之后是加法和减法;
bool b = true;
bool b2 = -b;    b2是true
对大多数运算符来讲,bool类型运算符计算式会被提升为int类型,b 为真,则被提升为int 1,-b = -1 != 0,所以b2是true;
int ival = 31/6;    整数相除还是整数,val = 5,余数被抛弃;
%--取余或取模,参与取余运算的对象必须都是整数类型;
double dval = 3.14;
ival / 12;    true
ival / dval;    false
除法运算,如果两个运算对象的符号相同,则商为正,否则商为负;
(-m)/n = m/(-n) = -(m/n);
(-m)%n = -(m%n);    (重要)
m%(-n) = m%n;
-21 % -8 = -5;
21 % -5 = 1;

逻辑和关系运算符

短路求值:&&--先求左侧运算值,左侧为真时继续求右侧;||--先求左侧运算对象的值,左侧为假时,对右侧对象取值,这种策略叫做~;

一些注意事项:
if(i < j < k)    这种写法是错误的
应该是:if(i < j && j < k)
if(val)    val是任意的非零值,条件为真
if(!val)    val = 0 时条件为真
if(i = j)    错误
应该是:if(i == j)
符合赋值运算符:
算数运算符:+=,-=,*=,/=,%=;
位运算符:<<=,>>=,&=,^=,|=;
等价于: a = a op b;
递增和递减运算符:
前置版本把值加一后之间返回改变了的运算对象;后置版本需要将原始值存储下来以便返回这个未修改的参数;如若必要,使用前置版本;
后置递增运算符的优先级高于解引用运算符,*pbeg++ 等价于 *(pbeg++);
eg
cout << *item++ << endl;
替代:
cout << *item <, endl;
++item;
第一种方式更加简洁;
*beg = toupper(*beg++)    这种时错误的,因为没有定义;

条件运算符

条件运算符:
cond?expr1:expr2;
运行过程:cond为真,对expr1求值并返回expr1,否则对expr2求值并返回expr2;
嵌套条件运算符:
finalgrade = (grade > 90) ? "high pass"
                          :(grade < 60) ? "fail" : "pass";
运行过程:检查grade > 90,则输出:high pass,否则进入:后面的分支,分支本身又是一个条件表达式;
注意:嵌套层数增加,代码可读性急剧下降,所以,最好别超过2~3层;条件运算符的优先级很低,一般使用的时候加上括号;

位运算符

(用到再详细写,现在没有用到呢!)

sizeof()运算符

sizeof()运算符返回一条表达式或者一个类型名字所占的字节数,满足右结合律,返回的是size_t类型;
两种形式:
sizeof(type);
sizeof expr;
第二种形式中,sizeof 返回的时表达式结果类型的大小,并不实际运算其运算对象的值;
Sales_data data, *p;
sizeof(Sales_data)    储存Sales_data类型对象所占空间大小;
sizeof(data)    data类型的大小,即sizeof(Sales_data)  ;
sizeof data.revenue    Sales_data的revenue成员对应的类型大小;
sizeof Sales_data::revenue    效果同上;
对string 和vector执行sizeof()只是返回该类型固定部分的大小,不会计算对象中元素占用了多少空间;
对数组执行sizeof()能得到整个数组所占空间大小;
sizeof(ia)/sizeof(*ia)    返回ia数组元素的个数;

逗号运算符

含有两个对象,按照从左到右的顺序一次求值,首先对左侧表达式求值 ,之后将求值结果丢弃掉,逗号运算符的真正结果是右侧表达式的值。如果右侧运算对象是左值,那么最终求值结果也是左值;常常用在for循环中;

vector<int>::size_type cnt = ivec.size();
//将把从size到1的值赋给ivec的元素
for(vector<int>::size_type ix = 0; ix != ivec.size(); ++ix,--cnt)
    ivec[ix] = cnt;

类型转换

如果两种类型可以相互转换,那么他们就是关联的。

自动执行的转换被称为隐式转换;

  1. 大多数表达式中,比int类型小的整型值首先提升为较大的整数类型;
  2. 在条件中,非布尔值转换成布尔类型;
  3. 初始化过程中,初始值转换成变量的类型;赋值语句中,右侧运算对象转换成左侧运算对象的类型;
  4. 运算对象有多种类型,需要转换成一种类型;
  5. 函数调用时会发生类型的转换;

算数转换:

运算符的运算对象转换成最宽的类型;
3.14159L + 'a'    'a'转换成int,int值转换成long double;
dval + ival    ival转换成double;
dval + fval    fval转换成double;
ival = dval    dval 转换成ival;
flag = dval    dval = 0 -- false ,否则 true
cval + fval    cval 提升为int,之后int转换成float;
sval + cval    sval和sval + cval  
lval + cval    cval 转换成long 
ival + uval    ival转换成unsigned long

其他隐式类型转换

数组转换成指针
int ia[10];
int *ip = ia;    ia转换成指向数组首元素的指针;
转换成bool类型
if(cp);
类类型定义转换
string s,t = "value";    字符串字面值转换成string 类型
while(cin >> s)    while的条件部分把cin转换成bool值
显示转换
这种方式本质上是很危险的,非必须,不使用;

 

致谢

《c++primer 第五版》

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值