1. 基础
1.1 基本概念
- 一元运算符和二元运算符
- 表达式求值时, 运算对象的类型可能会改变;(注意:
char,short
可能会提升为int
) - 重载运算符(overloaded): 运算符作用于类类型的运算对象时,用户自行定义运算符的含义,如IO库的
<<, >>
,string和vector使用的运算符 - 左值和右值:当被用作右值时,用的时对象的值(内容),用作左值时,用的是他的身份(内存中的位置);
decltype
作用于左值表达式时,得到的是引用类型
1.2 优先级和结合律
- 左结合律: 运算符优先级相同时,从左往右进行组合;
- 优先级规定了运算对象的组合方式,但是并没有说明其求值顺序,例如:
cout << i << ++i<<endl; //无法确定输出i值
- 规定了求值顺序的四个运算符:
&& || ?: ,
- 处理复合表达式的两条建议:
- 用括号强制限制表达式的组合关系
- 如果改变了某个运算对象的值,就不要在表达式中再使用该对象;
2. 算术运算符
- 算术运算符的求值结果和运算对象都是右值;
- 取余%:
(-m)/n = m/(-n) = (-m/n);
m%(-n) = m%n;
(-m)%n = -(m%n) //可以为负值
3. 逻辑和关系运算符
- 二者的返回值都是bool类型,其运算对象和求值结果都是右值;
- 进行比较时,除非比较对象是bool类型,否则不要用 true和false做运算对象
if(val==true)
时,若val不是bool值,则true被转换为1, 仅当val=1时返回true;
- 短路求值:
- 如果
&&
的左侧对象为真时,才对右侧对象求值; - 如果
||
的左侧对象为假时,才对右侧对象求值;
- 如果
4. 赋值运算符
- 赋值运算的结果是左侧运算对象,而且是一个左值;
- 满足右结合律;
5. 递增递减运算符
- 优先使用前置版本
前置版本对象本身作为左值返回,后置版本将对象的原始值拷贝后作为右值返回;例:
cout << *p++ <<endl; //尽管后置递增的优先级大于解引用, 但是其输出结果仍是(*p)的内容
6. 成员访问运算符
ptr -> mem
等价于(*ptr).mem
7. 条件运算符
cond ? expr1 : expr2
- 条件运算符只对expr中的一个进行求值;
- 当两个expr都是左值时或能转换为同一种左值类型时,结果为左值;否则为右值;
8. 位运算符
- 最好位运算符仅用于处理无符号数;
- 若运算对象对小整型,则会被自动提升为
int
9. sizeof运算符
sizeof
满足左结合律,结果为size_t
类型,返回的是字节数sizeof(type)
sizeof expr
: 返回表达式结果的大小,不计算其值
- sizeof(char) = 1;
- sizeof 引用类型,得到被引用对象空间大小
- sizeof 指针, 得到指针的大小
- sizeof(*p), 得到对象本身大小
- sizeof(数组),得到整个数组的空间大小
- 对于string和vector,只返回该类型固定部分大小,不计其元素所占空间;
10. 逗号运算符
11. 类型转换
- 如果两个类型可以相互转换,则称其为相互关联的;
隐式类型转换:
算术转换:
- 整型提升
- 无符号类型的转换要根据所占空间大小决定,若空间相等,
int -> uint
;若空间不等,遵从较大的运算对象;
- 命名的强制类型转换
- 通式:
cast-name<type>(expression)
static_cast<double>j;
:任何具有明确定义的类型转换,不包含底层constconst_cast<char *>
: 只能改变其常量属性,不能改变类型reinterpret_cast
: 为运算对象的位模式提供较低层次的解释;dynamic_cast
:支持运行时类型识别
c++中关于char型变量与字符串地址的输出
- 通式:
12. 运算符优先级