c++ primer知识点-第5章 表达式

目录

5.1 算术操作符

5.2 关系操作符和逻辑操作符

5.3 位操作符

5.4 赋值操作符

5.5 自增和自减操作符

5.6 箭头操作符

5.7 条件操作符

5.8 sizeof操作符

5.9 逗号操作符

5.10 复合表达式的求值

5.11 new和delete表达式

5.12 类型转换

 

表达式由一个或多个操作数通过操作符组合而成,每个表达式都会产生一个结果。

5.1 算术操作符

算术操作符(优先级相同时,操作符从左向右结合)

操作符 功能
+ 一元正号
一元负号
* 乘法
/ 除法
% 求余
+ 加法
减法

%只能用于整数,包括bool,char,short,int和long类型,以及对应的unsigned类型。

5.2 关系操作符和逻辑操作符

! 逻辑非 < 小于
<= 小于等于 > 大于
>= 大于等于 == 相等
!= 不等 && 逻辑与
|| 逻辑或    

1. 逻辑与、逻辑或操作符

短路求值;如果某边界条件使expr2的计算变得危险,则就应在该条件出现之前,先让expr1的计算结果为false。

2. 逻辑非操作符

3. 不应该串接使用关系操作符

4. 相等测试与bool字面值

直接用变量作为条件进行检测(可以转换为bool类型)

5.3 位操作符

位操作符使用整型的操作数。位操作符将其整型操作数视为二进制位的集合,为每一位提供检验和设置功能,还可用于bitset类型。

~ 位求反 << 左移
>> 右移 & 位与
^ 位异或 | 位或

对于位操作符,系统不能确保如何处理其操作数的符号位,因些强烈建议使用unsigned整数。

>>和<<操作符提供移位操作,其右操作数标志要移动的位数;左移操作符<<在右边插入0以补充空位;对于右移操作符>>,如果其操作数是无符号数,则从左边开始插入0;如果是有符号数,则插入符号位的副本或者0值。移位操作符的右操作数不可为负。

位与操作符&需要两个整型操作数,在每个位的位置,如果两个操作数对应的位都为1,则操作数结果中该位为1,否则为0。

位异或操作符^需要两个整型操作数,在每个位的位置,只有一个位为1,则操作数结果中该位为1,否则为0。

位或操作符|需要两个整型操作数,在每个位的位置,有一个或两个位为1,则操作数结果中该位为1,否则为0。

5.3.1 bitset对象或整型值的使用

设置第27位为1,其他为0。

重新设置第27位为0;

5.3.2 将移位操作符用于IO

IO操作符为左结合。

5.4 赋值操作符

赋值操作符的左操作数必须是非const的左值;赋值表达式的值是其左操作数的值,其结果的类型为左操作数的类型。

5.4.1 赋值操作的右结合性

5.4.2 赋值操作具有低优先级

谨防混淆相等操作符和赋值操作符。

5.4.3 复合赋值操作符

5.5 自增和自减操作符

只有必要时才使用后置操作符(前置操作符效率更高)。

1. 后置操作符返回未加1的值。

2. 在单个表达式中组合使用解引用和自增操作

5.6 箭头操作符

点操作符用于获取类类型对象的成员;如果有一个指向Sales_item对象的指针(或迭代器),则在使用点操作符前,需对该指针(或)迭代器进行解引用。

当然可以用->代替*

5.7 条件操作符

唯一的三元操作符。

1. 避免条件操作符的深度嵌套

2. 在输出表达式中使用条件操作符

条件操作符的优先级相当低,如果有一个更强大的表达式嵌入条件表达式时,通常必须用圆括号把条件表达式括起来。

5.8 sizeof操作符

sizeof操作符的作用是返回一个对象或类型名的长度,返回值的类型为size_t,长度的单位是字节。

将sizeof用于expr时,并没有计算表达式expr的值。特别是在sizeof *p中,指针p可以持有一个无效地址,因为不需要对p做解引用操作。

使用sizeof的结果部分地依赖所涉及的类型:

(1) 对char类型或值为char类型的表达式做sizeof操作保证得1。

(2) 对引用类型做sizeof操作将返回存放此引用类型对象所需的内存空间大小。

(3) 对指针做sizeof操作将返回存放指针所需的内存大小;注意,如果要获取该指针所指向对象的大小,则必须对该指针进行解引用。

(4) 对数组做sizeof操作等效于将对其元素类型做sizeof操作的结果乘上数组元素的个数。

5.9 逗号操作符

从左向右计算,结果是其最右边的表达式。

5.10 复合表达式的求值

5.10.1 优先级

5.10.2 结合性

赋值操作有右结合性,这个特性允许将多个赋值操作串接起来。

表 5.4. 操作符的优先级

Associativity

and Operator

操作符及其结合性

Function

功能

Use

用法

See

Page

参见页码

L

::

global scope(全局作用域)

:: name

p. 450

L

::

class scope(类作用域)

class :: name

p. 85

L

::

namespace scope(名字空间作用域)

namespace :: name

p. 78

L

.

member selectors(成员选择)

object . member

p. 25

L

->

member selectors(成员选择)

pointer -> member

p. 164

L

[]

subscript(下标)

variable [ expr ]

p. 113

L

()

function call(函数调用)

name (expr_list)

p. 25

L

()

type construction(类型构造)

type (expr_list)

p. 460

R

++

postfix increment(后自增操作)

lvalue++

p. 162

R

--

postfix decrement(后自减操作)

lvalue--

p. 162

R

typeid

type ID(类型 ID)

typeid (type)

p. 775

R

typeid

run-time type ID(运行时类型 ID)

typeid (expr)

p. 775

R

explicit cast(显式强制类型转换)

type conversion(类型转换)

cast_name <type>(expr)

p. 183

R

sizeof

size of object(对象的大小)

sizeof expr

p. 167

R

sizeof

size of type(类型的大小)

sizeof(type)

p. 167

R

++

prefix increment(前自增操作)

++ lvalue

p. 162

R

--

prefix decrement(前自减操作)

-- lvalue

p. 162

R

~

bitwise NOT(位求反)

~expr

p. 154

R

!

logical NOT(逻辑非)

!expr

p. 152

R

-

unary minus(一元负号)

-expr

p. 150

R

+

unary plus(一元正号)

+expr

p. 150

R

*

dereference(解引用)

*expr

p. 119

R

&

address-of(取地址)

&expr

p. 115

R

()

type conversion(类型转换)

(type) expr

p. 186

R

new

allocate object(创建对象)

new type

p. 174

R

delete

deallocate object(释放对象)

delete expr

p. 176

R

delete[]

deallocate array(释放数组)

delete[] expr

p. 137

L

->*

ptr to member select(指向成员操作的指针)

ptr ->* ptr_to_member

p. 783

L

.*

ptr to member select(指向成员操作的指针)

obj .*ptr_to_member

p. 783

L

*

multiply(乘法)

expr * expr

p. 149

L

/

divide(除法)

expr / expr

p. 149

L

%

modulo (remainder)(求模(求余))

expr % expr

p. 149

L

+

add(加法)

expr + expr

p. 149

L

-

subtract(减法)

expr - expr

p. 149

L

<<

bitwise shift left(位左移)

expr << expr

p. 154

L

>>

bitwise shift right(位右移)

expr >> expr

p. 154

L

<

less than(小于)

expr < expr

p. 152

L

<=

less than or equal(小于或等于)

expr <= expr

p. 152

L

>

greater than(大于)

expr > expr

p. 152

L

>=

greater than or equal(大于或等于)

expr >= expr

p. 152

L

==

equality(相等)

expr == expr

p. 152

L

!=

inequality(不等)

expr != expr

p. 152

L

&

bitwise AND(位与)

expr & expr

p. 154

L

^

bitwise XOR()

expr ^ expr

p. 154

L

|

bitwise OR(位异或)

expr | expr

p. 154

L

&&

logical AND(逻辑与)

expr && expr

p. 152

L

||

logical OR(逻辑或)

expr || expr

p. 152

R

?:

conditional(条件操作)

expr ? expr : expr

p. 165

R

=

assignment(赋值操作)

lvalue = expr

p. 159

R

*=, /=, %=,

compound assign(复合赋值操作)

lvalue += expr, etc.

p. 159

R

+=, -=,

   

p. 159

R

<<=, >>=,

   

p. 159

R

&=,|=, ^=

   

p. 159

R

throw

throw exception(抛出异常)

throw expr

p. 216

L

,

comma(逗号)

expr , expr

p. 168

 

5.10.3 求值顺序

复合表达式的处理指导原则:(1) 如果有怀疑,则在表达式上按程序逻辑要求使用圆括号强制操作数的组合。(2)如果要修改操作数的值,则不要在同一语句的其他地方使用该操作数。如果必须使用改变的值,则把该表达式分割成两个独立的语句:在一个语句中改变该操作数的值,再在下一个语句中使用它。(3)一个表达式里,不要在两个或更多的子表达式中对同一对象做自增或自减操作。

5.11 new和delete表达式

1. 动态创建对象的初始化

动态创建的对象可用初始化变量的方式实现初始化:

2. 动态创建对象的默认初始化

如果不提供显式初始化,动态创建的对象与在函数内定义的变量初始化方式相同,对于类类型的对象,用该类的默认构造函数初始化;而内置类型的对象则无初始化。对于提供了默认构造函数的类类型,没有必要对其对象进行值初始化(会自动调用)。而对于内置类型或没有定义默认构造函数的类型,采用不同初始化方式则有显著的差别:

 

3. 耗尽内存

如果new表达式无法获取需要的内存空间,系统将抛出名为bad_alloc的异常。

4. 撤销动态创建的对象

5. 零值指针的删除

安全。

6. 在delete之后,重设指针的值

一旦删除了指针所指向的对象,立即将指针置为0,这样就非常清楚地表明指针不再指向任何对象。

7. const对象的动态分配和回收

动态创建const对象:

动态创建的const对象必须在创建时初始化,并且一经初始化,其值就不能修改。对于类类型的const动态对象,如果该类提供了默认的构造函数,则此对象可隐式初始化。内置类型或未提供默认构造函数的类类型对象必须显式初始化。

8. 删除const对象

与普通对象的释放方式一样。

5.12 类型转换

C++定义了算术类型之间的内置转换尽可能防止精度损失。

5.12.1 何时发生隐式类型转换

在混合类型的表达式中,其操作数被转换为相同的类型;用作条件的表达式被转换为bool类型;用一表达式初始化某个变量,或一表达式赋值给某个变量,则该表达式被转换为该变量的类型。

5.12.2 算术转换

整型提升:所有比int小的整型,包括char、signed char、unsigned char、short和unsigned short,如果该类型的所有可能的值都能包容在int内,它们就会被提升为int型,否则将被提升为unsigned int。

1. 有符号和无符号类型之间的转换

包含short和int类型的表达式,short->int;如果int能容纳unsigned short,则unsigned short->int,否则unsigned short,int->unsigned int。同理,unsigned int->long,否则unsigned int,long->unsigned long。

对于包含signed和unsigned int型的表达式,其转换有副作用,尽量不要使用。

2. 理解算术转换

5.12.3  其他隐式转换

1. 指针转换

数组:

不将数组转换为指针的情况有:数组用作取地址(&)操作符的操作数或sizeof操作符的操作数时,或用数组对数组的引用进行初始化时。

2. 转换为bool类型

0、null或空字符转换为false。

3. 算术类型与bool类型的转换

将bool对象转换为算术类型时,true变成1,而false则为0。

4. 转换与枚举类型

C++自动将枚举转换为整型。

5. 转换为const对象

当使用非const对象初始化const对象的引用时,系统将非const对象转换为const对象,还可以将非const对象的地址(或非const指针)转换为指向相关const类型的指针:

 

6. 由标准库类型定义的转换

5.12.4 显式转换

static_cast,dynamic_cast,const_cast,reinterpret_cast。

5.12.5 何时需要强制类型转换

用于强制覆盖通常的标准转换。

5.12.6 命名的强制类型转换

 

1. dynamic_cast

2. const_cast

将转换掉表达式的const性质。

3. static_cast

编译器隐式执行的任何类型转换都可以由static_cast显式完成。

4. reinterpret_cast

通常为操作数的位模式提供较低层次的重新解释。

 

尽量避免使用强制类型转换。

5.12.7 旧式强制类型转换

作者: 勿慢牛

安全方向,化學/化工專業,主要關注學佛、計算化學、C++、Python、計算機、古文化、哲學、思維方向,渴求與有共同興趣的朋友交流,詳情請查看“關于”頁面。

发表评论

电子邮件地址不会被公开。 必填项已用*标注