C++ Primer 读书笔记 – 第五章

来源:互联网 发布:软件开发网校 编辑:程序博客网 时间:2024/05/29 16:34
 

C++ Primer 读书笔记 – 第五章

分类: C++ pirmer 读书笔记 71人阅读 评论(0) 收藏 举报
读书c++delete编译器initializationobject

第5章 表达式

⒈ 表达式(expression_r)是一个C++程序中最低级的计算,由一或多个用一个操作符(operator)连接起来的操作数(operands)组成
⒉ 每个表达式都产生一个结果。表达式可以用作操作数,因此可用多个操作符编写复合表达式
⒊ 在求解表达式的过程中如果需要储存运算结果,编译器会自动创建没有名字的临时对象(temporary object),这些对象会在外围最大的表达式结束后释放
⒋ 表达式是否合法、合法表达式含义如何(执行什么操作、结果是什么类型)均取决于操作数的类型

⒌⒈ 算术操作符
⒈ 按优先级从高到低排列为:
一元正+, 一元负-; 乘法*, 除法/, 取模%; 加法+, 减法-
⒉ 关于除法/
⑴ 两整数相除结果仍为整数,商的小数部分被截去
⑵ 一正一负两整数相除,结果值向
0一侧还是向-∞一侧取整依赖于机器
⒊ 关于取模
⑴ 操作数只能为整型
⑵ 两操作数均为负时结果为负或0;
两操作数一正一负时,结果的符号随哪个操作数而定依赖于机器

⒌⒉ 关系操作符和逻辑操作符
⒈ 按优先级从高到低排列为:
逻辑非!; 小于<, 小于等于<=, 大于>, 大于等于>=; 相等==, 不等!=; 逻辑与&&; 逻辑或||
⒉ 关系操作符和逻辑操作符接受算术或指针型操作数,并返回 bool 型值
逻辑操作符视其操作数为条件表达式
⒊ 逻辑与&&和逻辑或||操作符支持短路求值(short-circuit evaluation)
⒋ 不应串接使用关系操作符
形如i<j<k的表达式得不到预期结果

⒌⒊ 位操作符
⒈ 按优先级从高到低排列为:
位取反~; 左移<<, 右移>>; 位与&; 位异或^; 位或|
⒉ 位操作符使用整型操作数,将其视为二进制位的集合
由于负整数的符号位如何处理依赖于机器,因此应使用 unsigned 整型操作数

⒌⒋ 赋值操作符
⒈ 赋值操作符的左操作数须为非 const 左值
赋值表达式的结果即为其左操作数(左值)
⒉ 赋值操作符从右向左结合,因此当各操作数都有相同的通用类型时,允许在一个表达式中进行多次赋值,如:
i = j = k = 0;
⒊ 复合赋值操作符
对于任意二元算术操作符或二元位操作符 op
a op= b;
相当于
a = a op b;
二者显著的差别在于前者只计算了一次左操作数,后者则计算了两次

⒌⒌ 自增和自减操作符
⒈ 自增++和自减–操作符为对象加1或减1提供了方便简短的实现方式,有前置和后置两种使用形式
前置操作返回加(减)1后的对象(左值),后置操作返回操作数的原值(右值)
⒉ 出于性能考虑,应只在必要时才使用后置操作符
后置操作符需要先保存原值以便返回,而前置操作符只需加(减)1后直接返回对象即可

⒌⒍ 箭头操作符
箭头操作符用于获取指针指向类类型对象的成员。
下面两个表达式等价:
p->foo;
(*p).foo;

⒌⒎ 条件操作符
⒈ 条件操作符是C++中唯一的三元操作符,能将简短的 if-else 语句嵌入表达式
格式为 cond ? expr1 : expr2
首先计算 cond 值,若为 true 则计算并返回 expr1, 为 false 则计算并返回 expr2
⒉ 避免深度嵌套以保证可读性

⒌⒏ sizeof 操作符
⒈ sizeof 操作符用于返回一个对象或类型的大小(单位字节,类型 size_t)
形式为 sizeof expr
或  sizeof(type_name)
⒉ sizeof 表达式的结果是编译时常量
对表达式使用 sizeof 时该表达式的值并不会被计算
⒊ 对数组作 sizeof 将得到整个数组在内存中的长度

⒌⒐ 逗号操作符
逗号表达式是一组由逗号分隔的表达式,从左向右计算并返回最右边表达式的值(若该表达式为左值则返回左值)

⒌⒒ new 和 delete 表达式
⒈ new 和 delete 表达式分别用于动态创建和释放单个对象或一个数组
⒉ new 表达式
⑴ new 表达式动态创建单个对象或一个数组,并返回指向该对象或数组首元素的指针
① 动态数组维数为0值时也将返回有效的非零指针,但不能解引用
② 可以创建动态的 const 对象或数组,它们无法修改但可以释放
③ 如果无法获取需要的空间,系统将抛出 bad_alloc 异常
⑵ 分配与对象(或数组元素)初始化
① 默认内置类型不初始化,类类型调用默认构造函数(必须提供)
单个对象: new [const] 类型名
一个数组: new [const] 类型名[维数]
② 添加空括号()可执行值初始化(value initialization)
即内置类型对象置为0,类类型对象调用默认构造函数(必须提供)
单个对象: new [const] 类型名()
一个数组: new [const] 类型名[维数]()
注:对于后者,我使用的编译器中,VC初始化后会把元素置为0,但mingw不会
③ 执行直接初始化
单个对象: new [const] 类型名(初始化式)
动态数组元素不支持类似初始化方式
⒊ delete 表达式
⑴ 由 new 动态分配的对象或数组需要显式地使用 delete 表达式释放(否则会造成内存泄漏)
⑵ delete ptr 和 delete[] ptr 分别释放单个对象和动态数组
① 如果指针不指向由 new 分配的对象,则对其 delete 不合法
例外:对零指针 delete 是合法的
② 读写已释放的对象或对同一内存空间多次 delete 都可能导致错误
因此 delete 之后应立即重置该指针的值(一般重置为0)
③ 释放动态数组如果丢掉方括号[],将可能导致编译器无法发现的错误

⒌⒑ 复合表达式的求值
⒈ 含有两个或以上操作符的表达式称为复合表达式(compound expression_r)
操作数和操作符的结合方式决定了符合表达式的值,而前者取决于操作符的优先级和结合性:
操作数优先与优先级更高的操作符结合;操作符优先级相同时则由结合性决定结合方向
⒉ 圆括号()凌驾于优先级之上
若不确定结合方式,则使用圆括号()强制确定操作数的组合
⒊ 结合方式确定并不意味着操作数的计算顺序并不确定
若修改了操作数的值,则不要在同一语句的其它地方再使用它,除非操作数的计算次序不成问题
⒋ 运算符优先级与结合性表

⒌⒓ 类型转换
⒈ 隐式类型转换
两个类型间存在可转换关系,则称两个类型相关
⑴ 何时发生
当编译器期望获得某种类型的数据却得到另一种类型的,就会尝试自动转换类型
具体情况包括:
① 表达式中不同类型的多个操作数被转换到同一类型
② 用作条件的表达式被转换为 
bool 型
③ 用一表达式对某变量初始化或赋值时,前者转换为后者的类型
④ 给函数传递实参和返回值时可能发生隐式类型转换
⑵ 内置类型转换规则
① 算术类型间的转换
ⅰ 浮点型转换为整型时小数部分被抛弃(在赋值、初始化等情况下发生)
ⅱ 二元(算术、关系等)操作符表达式中,为试图保留精度会把较小的类型转换为较大的类型
a类型提升
· 将比 int 小的整型提升为 int 或(当 int 不足以容纳原类型的所有可能值时)unsigned int
· 将 float 提升为 double
b si

0 0
原创粉丝点击