码迷,mamicode.com
首页 > 编程语言 > 详细

C++ Primer 第四版读书笔记(四)之表达式

时间:2014-12-29 15:20:31      阅读:221      评论:0      收藏:0      [点我收藏+]

标签:

表达式由一个或多个操作数通过操作符组合而成。最简单的表达式仅包含一个字面值常量或变量。较复杂的表达式则由操作符以及一个或多个操作数构成。

每个表达式都会产生一个结果。如果表达式中没有操作符,则其结果就是操作数本身的值。当一个对象用在需要使用其值的地方,则计算该对象的值。

操作符的含义——该操作符执行什么操作以及操作结果的类型——取决于操作数的类型。

C++提供了一元操作符和二元操作符两种操作符。作用在一个操作数上的操作符称为一元操作符。如曲地址符(&)和解引用操作符(*);而二元操作符则作用于两个操作数上,如加法操作符(+)和减法操作符(-)。

一、算术操作符

当只有一个操作数为负数时,求模操作结果值的符号可依据分子(被除数)或分母(除数)的符号而定。如果求模的结果随分子的符号,则除出来的值想零一侧取整;如果求模与分母的的符号匹配,则除出来的值向负无穷一侧取整。

二、关系操作符和逻辑操作符

关系操作符和逻辑操作符
操作符 功能
! 逻辑非
<
<=
>
>=
小于
小于等于
大于
大于等于
==
!=
等于
不等
&& 逻辑与
|| 逻辑或

2.1 逻辑与、逻辑或操作符

仅当逻辑与(&&)操作符的两个操作数都为true,其结果才得true。

对于逻辑或(||)操作符,只要两个操作数之一为true,它的值就为true。

注:逻辑与和逻辑或操作符总是先计算做操作数,然后再计算其右操作数。只有在仅靠左操作数的值无法确定该逻辑表达式的结果时,才会求解其右操作数。我们常常称这种求值策略为“短路求值”。

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

三、位操作符

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

位操作符
操作符 功能
~ 位求反
<<
>>
左移
右移
& 位与
^ 位异或
| 位或

位操作符操纵的整数的类型可以是有符号的也可以是无符号的。如果 操作数为负数,则位操作符如何处理其操作数的符号位依赖于机器。于是它们的应用可能不同:在一个应用环境中实现的程序可能无法用于另外一应用环境。

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

左移操作符(<<)在右边插入0以补充空位。对于右移操作符(>>),如果其操作数是无符号位,则从左边开始插入0;如果操作数是有符号位,则插入符号位的副本或者0值,如何选择需依据具体的实现而定。移位操作的右操作数不可以是负数,而且必须是严格小于左操作数位数的值。否则,操作的效果未定义。

3.1 bitset对象或整型值的使用

3.2 将移位操作符用于IO

四、 赋值操作符

复制操作数的左操作数必须是非const的左值。

五、自增和自减操作符

六、sizeof操作符

sizeof操作符的作用是返回一个对象或类型名的长度,返回值的类型为size_t,长度的单位是字节。sizeof表达式的结果时编译时常量,该操作符有以下三种语法形式:

sizeof(type name);

sizeof ( expr);

sizeof expr;

将sizeof应用在表达式expr上,将获得该表达式的结果的类型长度。

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

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

1、对char类型或值为char类型的的表达式做sizeof操作保证得1;

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

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

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

七、new和delete表达式

定义变量时,必须指定其数据类型和名字。而动态创建对象时,只需要指定其数据类型,而不必为该对象命名。取而代之的是,new表达式返回指向新创建对象的指针,我们通过该指针来访问此对象。

7.1 动态创建对象的初始化

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

int i(1024);

int *pi = new int(1024);

string s(10, ‘9‘);

string *ps = new string(10. ‘9‘);

C++使用直接初始化语法规则初始化动态创建的对象。如果提供了初值,new表达式分配到所需要的内存后,用给定的初值初始化该内存空间。

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

如果不提供显示初始化,动态创建的对象与函数内定义的变量初始化方式相同。对于类类型的对象,用该类的默认构造函数初始化;而内置类型的对象则无初始化。

7.3 耗尽内存

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

7.4 撤销动态创建的对象

动态创建的对象用完后,程序员必须显示地将该对象占用的内存返回给自由存储区。C++提供了delete表达式释放指针所指向的地址空间。

7.5 零值指针的删除

如果指针的值为0.则在其上做delete操作是合法的,但这样没有任何意义:

int *ip = 0;

delete ip;

C++保证:删除0值的指针是安全的。

7.6 在delete之后,重设指针的值

删除指针后,该指针变成悬垂指针。悬垂指针指向曾经存放对象的内存,但该对象已经不再存在了。悬垂指针往往导致程序错误,而且很难检测出来。

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

7.7 const对象的动态分配和回收

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

与其他常量一样,动态创建const对象必须在创建时初始化,并且一经初始化,其值就不能在修改。

警告:动态内存的管理容易出错

下面三种常见的程序错误都与动态内存分配相关:

(1)、删除(delete)指向动态分配内存的指针失败,因而无法将该块内存返还给自由存储区。删除动态分配内存失败称为“内存泄漏(memory leak)”。内存泄漏很难发现,一般需等应用程序运行了一段时间后,耗尽了所有的内存空间,内存泄漏才会显露出来。

(2)、读写已删除的对象。如果删除指针所指向的对象之后,将指针置为0值,则比较容易检测出这类错误。

(3)、对同一个内存空间使用两次delete表达式。当两个指针指向同一个动态创建的对象,删除时就会发生错误。如果在其中一个指针上做delete运算,将该对象的内存空间返还非自由存储区,然后接着delete第二个指针,此时则自由存储区可能会被破坏。

7.8  删除const对象

delete pci;

即使delete表达式的操作数是指向int型const对象的指针,该语句同样有效回收pci所指向的内容。

八、类型转换

表达式是否合法取决于操作数的类型,而且合法的表达式其含义也是由操作数类型决定。

如果这两个类型之间可以相互转换,则称这两个类型相关。

C++并不是把两个不同类型的值直接加在一起,而是提供了一组转换规则,以便在执行算术操作之前,将两个操作数转换为同一种数据类型。这些转换规则由编译器自动执行,无需程序员介入。因此,他们也被称为隐式类型转换。

8.1  何时发生隐式类型转换

编译器在必要时将类型转换规则应用到内置类型和类类型的对象上。在下列 情况下,将发生隐式类型转换:

1、在混合类型表达式中,其操作数被转换为相同的类型:

int ival;

double dval;

ival >= dval;//ival converted to double

2、用作条件的表达式被转换为bool类型:

3、用一表达式初始化某个变量,或将一表达式赋值给某个变量,则该表达式被转换为该变量的类型

8.2 算术转换

8.2.1 有符号与无符号类型之间的转换

若表达式中使用了无符号数值,所定义的转换规则需保护操作数的精度。unsigned 操作数的转换依赖于机器中整型的相对大小,因此,这类转换本质上依赖于机器。

8.3 其他隐式转换

8.3.1 指针转换

在使用数组时,大多数情况下数组都会自动转换为指向第一个元素的指针:

int ia[10];

int *ip = ia;

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

C++还提供了另外两种指针转换:指向任意数据类型的指针都可转换为void*类型;整型值常量0可转换为任意指针类型。

8.3.2 转换为bool类型

8.3.3 算术类型与bool类型的转换

8.3.4 转换与枚举类型

C++自动将枚举类型的对象或枚举成员转换为整型,其转换结果可用于任何要求使用整数值的地方。

九、显示转换

显示转换称为强制类型转换(cast),包括以下列名字命名的强制类型转换操作符:

static_cast、dynamic_cast、const_cast和reinterpret_cast。

9.1 何时需要强制类型转换

因为要覆盖通常的标准转换,所以需显示使用强制类型转换。

显示使用强制类型转换的另一个原因是:可能存在多种转换时,需要选择一种特定的类型转换。

9.2 命名的强制类型转换


C++ Primer 第四版读书笔记(四)之表达式

标签:

原文地址:http://blog.csdn.net/y601500359/article/details/42235713

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!