第五章 表达式
1.求余操作符的操作数只能为整型(包括bool,char,short,int,long类型以及对应的unsigned类型);
2.逻辑与和逻辑或操作符总是先计算其左操作数,然后再计算右操作。它们的求值策略为“短路求值”——只有在仅靠左操作数的值无法确定该逻辑表达式的结果时,才会求解其右操作数;
3.不能串接使用关系操作符,因为关系操作符返回bool类型的结果;(如i < j < k 应写成 i < j && j < k)
4.对于位操作符,由于系统不能确保如何处理其操作数的符号位,所以建议使用unsigned整型操作数;
5.移位操作的右操作数不可以是负数,且必须是严格小于左操作数的位数的值,否则,操作效果是未定义的;
6.赋值操作具有右结合性:
int i = j = 520; //ok, j = 520, i = j;
7.谨防混淆 = 与 == :
if (i = 42) //将42赋给i, 此时i非0,if条件成立
if (i == 42) //检查i是否等于42
8.自增,自减操作符:
前置操作返回加1后的值,所以返回对象本身,是左值;
后置操作返回的是右值;
**前置操作的性能比后置操作好: 前置操作只需加1后返回结果即可;而后置操作需要先保存原来的值,以便返回未加1前的值为操作结果(对于整型对象和指针,编译器可优化这项工作,但是对复杂的迭代器类型,可能会产生比较大的性能差异);
9.
cout << *iter++ << endl;
//等价于:
cout << *(iter++) << endl;
//等价于:
cout << *iter << endl;
++iter;
//后自增操作优先于解引用操作,故等价于*(iter++),上例中,iter先自增,然后(iter++)返回的值是自增前的值,故解引用的是自增前的值;
10.sizeof操作符:
a.首先,它是一个操作符,而不是函数;
b.返回类型为size_t,单位是字节;
c.sizeof操作符不能用于函数类型(即函数指针类型,注意与函数返回值区分),不完全类型或位字段(不完全类型指具有未知存储大小的数据类型,如未知存储大小的数组类型array[]、未知内容的结构或联合类型、void类型等);
d.对函数调用使用sizeof,在编译阶段会被函数返回值的类型取代(注意,并不执行函数);
e.**sizeof并不计算表达式的值,它的内容(即括号里的部分)将会被替换成类型——计算结果的类型,即返回的是表达式的计算结果的类型大小:
char ch = 1;
int num = 1;
int n1 = sizeof(ch+num);
int n2 = sizeof(ch = ch+num);
/* 结果:
* ch = 1;
* n1 = 4;
* n2 = 1;
* 解析:
* ch+num的类型为int,故n1 = sizeof(int) = 4;
* ch = ch+num的类型为char,故n2 = 1;
* 而sizeof并不对表达式求值,所以ch的值不变;
* /
f.当操作数具有数组类型时,其结果是数组的总字节数;
g.当操作数是联合类型时,sizeof是其最大字节成员的字节数;
h.当操作数是结构类型时,sizeof并不等于成员类型的总字节数,因为结构体存在成员对齐,所以可能会有字节填充;
(简单的介绍:
1.结构体大小等于结构体内最大成员大小的整数倍;
2.结构体内成员的首地址相对于结构体首地址的【偏移量是其类型大小的整数倍】,比如double型成员的相对于结构体的偏移量应该是8的倍数;
3.为满足以上规则,编译器会在结构体成员之后进行字节填充。
**因此在结构体成员的顺序安排上需要仔细设计,以节省内存。
)
i.不能对void进行sizeof操作,但可以对void*进行sizeof操作(4byte);
j.sizeof能求静态分配内存的数组长度(注意char数组最后的’\0’);
注意形参数组:
void fun(int array[10])
{
int n = sizeof(array);
}
此处n的值为4,因为此处的array被转换成一个int类型的指针(因此在函数间传递数组时,最好增加一个size参数);
k. sizeof不能求得动态分配的内存大小!
int *a = new int[10];
int n = sizeof(a);
此处n为4,因为a是指针!
l. string是C++类型的字符串,是一个类,所以sizeof(s)表示的并不是字符串的长度,而是类string的大小;
m. sizeof不能用于求结构体的位域成员的大小,但是可以求得包含位域成员的结构体的大小:
位域:类型大小都是以字节为基本单位的,1byte等于8bit。char类型为1byte,即8bit,所以可以定义2^8 = 256个数。然而sizeof(bool) = 1,而bool只表示true和false两个数,本来只需要1bit但是却占用了8bit。
通过位域可对内存进行精打细算,简单来说,在结构体成员变量后面跟一个冒号+一个整数,就代表位域:
struct A
{
bool b:1;
char ch1:4;
char ch2:4;
}item;
以上b,ch1,ch2即位域成员,使得b只占用1个bit,ch1,ch2各占用4bit。
注意,位域变量只能在结构体,类,union中使用。
11.逗号表达式的结果是其最右边表达式的值;
12.
int *pi = new int; //没有初始化
int *pi = new int(); //初始化为0
13.对零值指针的删除是合法的,但是并没有意义;
14.一旦删除了指针所指向的对象,应立即将指针置0,在使用指针前进行检查,以免误用;