【C++Primer】第4章:表达式

第4章 表达式

4.1 基础

函数调用也是一种特殊的运算符

一些符号既能作为一元运算符,也能作为二元运算符,具体由上下文决定。

左值可以位于赋值语句的左侧,右值则不能。

当一个对象被用作右值的时候,用的时候对象的值(内容)

当对象被用作左值的时候,用的是对象的身份(在内存中的位置)

使用decltype的时候,如果表达式求值结果是左值,得到一个引用类型

假设p的类型是int*
decltype(*p)的结果是 int&
decltype(&p)的结果是 int**,即指向整型指针的指针

求值顺序

int i = f1() * f2();   //未规定先调用f1()还是f2()
int i = 0;
cout << i << " " << ++i << endl;  //未定义的  不管哪种答案都是错误的

4.2 算术运算符

算术运算符的运算对象和求值结果都是右值

image-20211220105748582

左结合律:优先级相同时按照从左到右的顺序进行结合

%取余的运算对象必须是整数类型

C++11新标准规定商一律向0取整(即直接切除小数部分)

(-m)/n和m/(-n)都等于-(m/n)

m%(-n)等于m%n

(-m)%n等于-(m%n)

4.3 逻辑和关系运算符

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

逻辑运算符和关系运算符的返回值都是布尔类型

两类运算符的运算对象和求值结果都是右值

image-20211220111655150

算术>关系>逻辑

逻辑运算符规定了运算对象求值的元素顺序

4.4 赋值运算符

赋值运算符的左侧运算对象必须是一个可修改的左值。

赋值运算满足右结合律

int ival, jval;
ival = jval = 0;
int ival, *pval;
ival = pval = 0;   //错误,不能把指针的值赋给int

4.5 递增和递减运算符

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

两种运算符必须作用于左值运算对象。前置版本将对象本身作为左值返回,后置版本则将对象原始值的副本作为右值返回。

前置版本性能好

当前置和后置效果一样时,我们最好坚持用前置版本

auto pbeg = v.begin();
//输出元素直到遇到第一个负值为止
while(pbeg!=v.end() && *pbeg>=0){
    cout << *pbeg++ << endl;  //输出当前值并将pbeg向前移动一个元素
}

后置递增运算符优先级高于解引用运算符。*pbeg++等价于*(peg++)

简洁是一种美德

方法一比方法二好,要习惯方法一的写法

//方法一
cout << *iter++ << endl;

//方法二
cout << *iter << endl;
++iter;

4.6 成员访问运算符

string s1 = "a string", *p = & s1;
auto n = s1.size();
n = (*p).size();
n = p->size();
n = *p.size();  //错误,解引用运算符优先级低于点运算符 

4.7 条件运算符

cond ? expr1 : expr2

string finalgrade = (grade < 60) ? "fail" : "pass";
finalgrade = (grade > 90) ? "high pass" 
    					  : (grade < 60) ? "fail" : "pass"; 

条件运算符满足右结合律

嵌套影响代码可读性,做好别超过三层

4.8 位运算符

image-20211220152517837

image-20211220152651091

取反如下:

image-20211220152830843

位与,位或,位异或运算符

image-20211220152948286

注意逻辑或(||)与位或(|)的区别;逻辑与(&&)与位与(&)的区别。

4.9 sizeof运算符

满足右结合律,所得的值是size_t类型

运算符的对象有两种形式

sizeof(type)
sizeof expr

image-20211220154807240

sizeof *p等价于sizeof(*p)

image-20211220155019019

image-20211220155030281

求arr数组的元素个数

constexpr size_t s2 = sizeof(arr)/sizeof(*arr);
int arr2[s2];

4.10 逗号运算符

规定了运算对象求值的顺序,从左到右

4.11 类型转换

隐式类型转换

int ival = 3.541 + 3; //隐式转换  int 3转换成double 3.0; ival为double 6.541 再转换成int 6 

image-20211220160606070

image-20211220162936546

image-20211220162951871

显式类型转换

cast-name<type>(expression);

cast-namestatic_cast、dynamic_cast、const_cast、reinterpret_cast中的一种

static_cast,只要不包含底层const,static_cast非常有用

强制类型转换告诉读者和编译器,我们知道并不在乎潜在的精度损失。

double slope = static_cast<double>(j) / i;

const_cast,只能改变运算对象的底层const

const char *pc;
char *p = const_cast<char*>(pc);

旧式的强制类型转换:

type (expr);  //函数形式的强制类型转换
(type) expr;  //C语言风格的强制类型转换

image-20211220165905848

image-20211220170047602

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zdb呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值