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

2009年1月02日    分类:C++, 原创   浏览次数:6 

目录

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。

bitset<30> bitset_quizl; //bitset solution
unsigned long int_quizl = 0; //simulated collection of bits
bitset_quizl.set(27); //inside student number 27 passed
int_quizl |= 1UL << 27;

重新设置第27位为0;

bitset_quizl.reset(27);
int_quizl &= -(1UL << 27);

5.3.2 将移位操作符用于IO

IO操作符为左结合。

5.4 赋值操作符

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

5.4.1 赋值操作的右结合性

ival = jval = 0; //从右向左结合

5.4.2 赋值操作具有低优先级

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

5.4.3 复合赋值操作符

a op = b; //op 可以是以下操作符之一: +=, -=, *=, /=, %=, <<=, >>=, |=, ^=

5.5 自增和自减操作符

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

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

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

*iter++; //解引用操作*的操作九是iter未加1前的副本。

5.6 箭头操作符

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

(*sp).Sales_item(item2); //注意不要丢掉()

当然可以用->代替*

sp->.Sales_item(item2); //就不用()了

5.7 条件操作符

唯一的三元操作符。

cond ? exp1 : exp2;

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

int max = i > j
		? i > k ? i : k
		: j > k ? j :k; //-->
int max = i;
if (j > max)
   max = j;
if (k > max)
   max = k;

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

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

5.8 sizeof操作符

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

sizeof (type name);
sizeof (expr);//将sizeof应用在表达式expr上,将获得该表达式的结果的类型长度
sizeof expr;//the same as above

将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 结合性

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

ival = jval = kval = lval

表 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. 动态创建对象的初始化

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

int *pi = new int(1024); //object to which pi points is 1024
string *ps = new string(10, '9'); //*ps is "9999999999"

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

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

int *pi = new int; //pi points to an uninitialized int
int *pi = new int(); //pi points to an int value-initialized to 0

 

3. 耗尽内存

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

4. 撤销动态创建的对象

delete 指针

5. 零值指针的删除

安全。

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

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

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

动态创建const对象:

const int *pci = new const int(1024);

动态创建的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. 指针转换

数组:

int ia[10];
int *ip = ia;

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

2. 转换为bool类型

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

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

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

4. 转换与枚举类型

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

5. 转换为const对象

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

int i;
const int cj = 0;
const int &j = i;
const int *p = &ci;

 

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

5.12.4 显式转换

static_cast,dynamic_cast,const_cast,reinterpret_cast。

5.12.5 何时需要强制类型转换

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

5.12.6 命名的强制类型转换

cast-name<type>(expression); /* cast-name = static_cast,dynamic_cast,
                                                const_cast,reinterpret_cast */

 

1. dynamic_cast

2. const_cast

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

3. static_cast

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

4. reinterpret_cast

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

int *ip;
char *pc = reinterpret_cast<char*>(ip);

 

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

5.12.7 旧式强制类型转换

type (expr);
(type) expr;
标签: ,      订阅此文  

本文地址:http://klniu.com/post/c-primer-knowledge-5/

相关文章

  1. c++ primer知识点-第6章 语句
  2. c++ primer知识点-第4章 数组和指针
  3. c++ primer知识点-第3章 标准库类型
  4. c++ primer知识点-第2章 变量和基本类型
  5. c++ primer知识点-第1章 快速入门


28 queries in 0.710 秒.