C++ primer读书笔记2(表达式)

来源:互联网 发布:碣石正车行淘宝店 编辑:程序博客网 时间:2024/06/06 03:14
表达式
1 算术运算符的求余,相除
运算符要数要注意的是带有符号的整数相除,求余数。如果两个数都为正,那么除法和求余的结果都为正或者0.如果两个数都为负数,那么除法的结果为整数或者0,余数的结果为负数或者0.如果两个数一正一负,那么求余和相除结果都取决于机器。如果求余的结果随分子而定,那么除出来的值向零一侧取整,如果求余结果跟随分母而定,那么除出来的结果向负无穷靠近。
即:
-21  ÷ 5 = -4 + -1;21 ÷ -5 = -4 + 1; (机器1,求余取决于分子)
-21  ÷ 5 = -5 + 4; 21 ÷ -5 = -5 + -4;(机器2,求余取决于分母)


2 算数运算符的优先级
算数运算中一元运算符只有 +,-,表示取正,取负,级别最高;二元运算符有*,/,%,+,-。


3 关系操作符的短路求值
关系运算符从做左计算,一旦计算出的结果能够确定整个结果,那么便停止计算余下的。


4 关系运算符都能产生bool值。


5 位操作符
种类有~(非),<<(左移),>>(右移),&(位与),^(位异或),|(位或);位操作符操纵的整数可以为正也可以为负,如果为负数则取决于机器,所以在做位操作的时候一定要注意机器。


6 bitset类
bitset类对象可以方便的操纵每一位的值,不用去用位操作符进行复杂的组合方式。


7 重载的移位操作符
<<(左移),>>(右移)。可以当做标准输入输出,这类操作符具有从左到右的结合性。移位操作符优先级比算数低,比关系高,返回的是cout或者cin等流格式对象。
8 赋值操作符 = 具有右结合性,赋值操作符的优先级是相当的低,比关系运算符还低。


9 自增自减操作符
分为前自增,后自增,前自减,后自减。其中后自增,后自减的优先级要高于前自增,前自减,同时还高于解引用操作符*。因此*iter++ == *(iter++) =={*iter;iter++} 。注意要把自增操作符看成一个具有返回值的函数,那么后自增操作符iter++表示的是返回值是iter,iter自身的值+1.


10 条件操作符
exp1?exp2:exp3;是C++中唯一的一个三目操作符。


11 sizeof 操作符
对数组做sizeof运算,将返回数组元素的个数乘以元素的大小的空间大小。


12 逗号操作符,
逗号表达式是一组由逗号分隔的表达式,这些表达式从左向右计算。结果是最右边表达式的结果,所以如果在条件判断中遇到“,”要知道怎么判断。


13 符合表达式求值时要注意结合性,相同级别的操作符的话,从左到右的结合性跟从右到左的结合性计算的结果是不一样的。并且千万注意如要要修改表达式的操作数,则不要在同一个句子使用该操作数。
如 if(ia[index++] < ia[index]);等同于
if(ia[index] < ia[index]);  //从右到左计算
if(ia[index] < ia[index+1]);//从左到右计算


14 动态创建对象的初始化
动态对象的初始化分为显式初始化和隐式初始化。按照对象类型又分为类类型对象初始化,内置类型对象初始化。
显式 int *p = new int(100); //p point to an object whose value is 100
显式 int *s = new string(2,'a');//s point to an object whose value is "aa"
隐式 int *p = new int;  // don't have a initialize.
隐式 int *s = new string; //string is initialized to a empty string 


15 隐式类型转换
发生隐式类型转换的情况:
在混合类型表达式中,int i;double j;i+j;
在条件表达式中,int i;if(i);//i is converted to bool
用于表达式初始化某一变量,或者赋值给某一变量。int value = 3.14;//3.14 converted to 3.


16 算术的隐式转换
算术转换主要是将几个不同长度类型的操作数转换成宽度最宽的操作数类型,如short ,int一起做运算,会转化成int。注意signed 和unsigned之间转换时候的规则,规则1:例如unsigned short 和int时候,如果int 能够表达所有的unsigned short ,那么两者将会转换成int,否则转换成unsigned int;规则2:unsigned int 和int之间进行计算时,会将signed转换成unsigned,这往往会导致错误的发生,并且难以发现错误。


17 指针的隐式转换
数组的隐式转换最常见。int array[10]; int *p = array //convert array to point to first element
但是也有例外,对数组取地址 &array(表示一个指向10个int类型大小的指针或者地址);sizeof(array),也是一个道理。


18 枚举类型转换
枚举类型中的元素都是整数,但是具体是什么类型的整数取决于枚举对象中的最大值,并且依赖于机器,但是有一点是可以确定的,枚举类型的对象至少是int 类型的。 


19 非const对象,const对象
可以用非const 对象初始化const类型对象,也可以用指向非const类型的指针转换为指向const对象的指针。
int i = 0;
const int j = i;
i = 5;
const int *p = &i;
20 流格式对象的转换
如 while(cin〉>> str),不管读取结果是否正确,返回值都是cin,但是在条件语句中要将istream类型转换成bool类型,此时就要检查流的状态,判断流是否为正常状态。


21 显式格式转换
C++中总共有四种显式格式转换(强制类型转换):static_cast,dynamic_cast,const_cast,reinterrept_cast.
(1)const_cast:用来增加或者去掉const性质。但是const_cast<type>中的type只能是指针或者引用,不能使别的类型。
(2)static_cast:编译器执行的任何隐式类型转换都可以通过static_cast来完成。
(3)reinterpret_cast:支持任何类型的指针之间的相互转换。也支持指针和整数之间的相互转换。但是用起来可能很危险。举例
int *p = new int(49);
char *pc = reinterpret_cast<char*>(p);
std::cout<<*pc<<endl;// the result is 1.
reinterpret_cast就是重新解释内存中的2进制数据类型。
(4)dynamic_cast: 用于运行时类型识别,多用于继承相关的方面,如:
if (Derived *derivedPtr = dynamic_cast<Derived*>(basePtr))
{//use the derived object to which derivedPtr points}
else
{//use the base object to which basePtr points}
dynamic_cast 涉及运行时类型检查。如果绑定到指针或者引用的对象不是指定的的目标对象时,则dynamic_cast 失败。如果转换到指针类型的dynamic_cast失败,则dynamic_cast的结果是0.如果转换到引用类型的dynamic_cast 失败,则抛出bad_cast类型的异常。
22 旧式的强制类型转换
旧式强制类型转换的格式(type)exp;在合法的使用const_cast ,static_cast的地方,旧式的强制类型转换提供与各自对应的转换机制。如果两种转换都不合法,那么旧式强制类型转换就执行跟reinterpret_cast的功能。
int *p;char *pc = (char*)p; // 这里等同于reinterpret_cast