接着前面的内容,我们继续学习。乘风破浪会有时,直挂云帆济沧海!加油
1、c++定义了一元和二元运算符。
2、关于左值和右值(c++表达式可以分为左值和右值):
(1)左值可以在赋值语句的左侧(用的是内存地址)和右侧(用的是内容);
(2)右值只能在赋值语句的右侧(用的是内容);
(3)左值分配有内存空间而右值则没有分配。
3、使用关键字decltype时,左值和右值有所不同:
(1)decltype作用于表达式生成左值;
(2)取地址运算符生成右值,解引用运算符生成左值;
int *p;
decltype(*p);//结果是:int & ---解引用运算符得到的是个左值(对象),decltype作用于左值返回一个引用类型 i
decltype(&p);//结果是:int**--取址运算符得到的是个右值(地址),decltype作用于右值返回一个右值
4、对于那些没有指定执行顺序的运算符来说,如果表达式指向并修改了同一个对象,将会产生未定义的行为。
int i = 0;
cout << i << " " << ++i << endl;//产生未定义的行为因为<<没有定义执行顺序
5、有4种运算符明确规定了运算对象的求职顺序。
(1)&&:规定先求左侧对象的值(只有左侧为真才求右侧的值)
(2)||:只有左侧为假才求右侧值
6、关于正确处理表达式的建议:
(1)、拿不准的时候使用括号
(2)、在一个表达式中不要对同一对象进行操作(例外:*++iter当改变运算对象的字表达式是另外一个表达式的运算对象)
7、只有整数才能进行取余运算。
8、关系运算符作用于算术类型和指针类型,逻辑运算符作用于能转换为bool类型的类型,这两类运算符的运算对象和结果都是左值。
9、关系运算符满足左结合律
10、执行赋值运算符不能进行窄化转换
11、赋值运算符满足右结合律
12、因为赋值运算符的优先级低于关系运算符,所以条件语句中赋值部分应该加上括号。
13、递增和递减运算符(除非必须,否则不要使用递增和递减运算符):
(1)前置++/–:执行递增/递减操作,返回最新的值
(2)后置++/–:执行递增/递减操作,返回原来的副本
14、后置递增的优先级高于解引用运算符(*++iterator)
15、解引用运算符的优先级低于点运算符((*p).size())
16、箭头运算符作用于一个指针类型的对象返回一个左值,点运算符依赖与成员的对象
17、条件运算符满足右结合律,条件运算符的嵌套最好不要超过三层。
finalgrade = (grade > 90 ) ? "high pass"
: (grade < 60) ? "pass";
18、位运算符作用于整数类型的运算对象,并把运算对象看成是二进制位的集合。
19、建议将位运算符作用于无符号类型,位求反运算符(~)将对象逐位求反返回一个新的值。
20、移位运算符的优先级比运算符的优先级低,比关系运算符、赋值运算符合条件运算符的优先级高。
21、sizeof运算符:返回一个表达式或一个类型名字所占的字节数(size_t类型),满足右结合律。
22、sizeof的运算结果部分依赖于其作用的类型:
- 对char或者类型为char的表达式执行sizeof,结果为1
- 对引用类型执行得到引用对象所占空间的大小
- 对指针执行得到指针本身所占的大小
- 对解引用指针执行,得到指向对象的空间大小
- 对数组执行得到真个数组的大小
- 对string和vector执行得到该类型固定部分的大小
23、逗号表达式:首先求左侧表达式的值,然后将结果丢掉求右侧表达式的值。逗号表达式的真正结果是右侧表达式的值。
24、隐式类型的转换:
- 比int小的整数值首先提升为较大的整数类型
- 非布尔值转换为布尔值
- 赋值语句中,右侧对象被转换为左侧对象
- 算术运算和关系运算的运算对象有多种类型,需要转换为一种类型
25、算术转换:把一种算术类型转换为另外一种算术类型。
26、整形提升:把小的整数类型转换为大的整数类型
27、数组转换为指针:大多数时,数组自动转换为指向数组首元素的指针
28、当数组被用作decltype的参数,或者作为去地址(&)、sizeof、typeid等运算符的对象时上面的转换不会发生。
29、指针的转换:常量整数值0或者字
面值nullptr能转换为任意指针类型,任意指针类型可以转换为void*,void*可以转换为const void*.
30、 显示转换:命名的强制类型转换 –cast-name<type>(expression),type转换的目标类型,expression是要转换的值。如果type是引用类型,则结果是左值。cast-name是static_cast,dynamic_cast,const_cast和reinterpret_cast中的一种。
31、static_cast任何具有明确定义的转换,只要不包含底层const(指向常量的指针),都可以使用static_cast。
int a =23;
int const * p = &a;//底层的const 指向常量的指针
//-----------------------------
int *const p = &b;//顶层const 指向对象的常量指针
//--------------------------------
double slope = static_cast<double>(j);
31、const_cast只能改变运算对象的底层const
const char * pc;//底层的const 指向常量的指针
char * = const_cast<char*>pc;
32、reinterpret_cast:为运算对象的位模式提供较低层次上的重新解释。
33、尽量避免强制类型转换。