运算符
运算类型转换
类型提升
重载运算符
。。。
左值和右值
等号两边的对象
优先级和结合律
运算符的优先级和运算顺序(左结合律)
求值顺序
对于未制定求值顺序的表达式,求值的时候产生的行为是未定义的。
cout << i << " " << i++ <<endl;
cout中没有定义如何对运算对象求值,所以是未定义的,最终结果取决于编译环境。
4种明确了运算对象求值顺序的运算符
&&
||
?:
,
运算对象的求值顺序和优先级与结合律无关。
c = f() + g() * h() +j();
优先级规定g和h的返回值相乘
结合律规定f和g与hde乘积相加,在加上j;
对于这几个函数的调用顺序未规定。
如果这几个函数对同一个对象进行了修改,那么将会产生未定义行为。
这个时候可以使用括号进行强制规定。
算术运算符
注意一点:
m%n的运算定义:如果m,n是整数且n非0,
表达式(m/n)*n+m%n与m相等
所以可以推出来
m%(-n) = m%n;
(-m)%n = -(m%n);
可以记作符号随m。这一点和乘除法不一致。
关系运算符
短路求值
赋值运算符
始终注意赋值运算符的优先级较低。0
注意:
C++中混用后置递增运算符和解引用运算符。
auto p = a.begin();
cout << *p++<<endl;
使用p当前的值,并将指针后移。
运算符对象可以按照任意顺序求值
for(auto i = a.begin();i!=a.end();++i)
*i = toupper(*i++)
//上述行为是未定义的;
//编译器可能采用下述任意一种顺序
*i = toupper(*i),i++;
*(i++) = toupper(*i);
//或者其他任何方式。
sizeof运算符
逗号运算符
从左到右依次计算。
类型转换
隐式类型转换
发生情况:
- 大多数表达式中,比int小的提升为int
- 在条件中菲bool转换为bool值
- 初始化,初始值转换为变量类型,赋值运算中,右侧转化为左侧对象类型。
- 算术运算和关系运算的运算对象需要转换为同一种类型。
- 函数调用时发生的类型转换
算术转换
运算符的运算对象会自动转换为最宽的类型。
整型提升
- 小整型会转换为较大整型,int
- 较大的char类型会转换为int,unsinged int;long;unsigned long;long long;unsigned long long
其他隐式类型转换
- 数组转换为指针。
- 指针转换为bool值
- 类类型的转换(参考C++ Primer Plus 的转换构造函数)
显式转换
C类型的强制类型转换。
double a = 10.9;
double b = 18.8;
int c = (int)a + (int)b;
C++类型转换
类似于
cast-name< type>(expression)
type是要转换的目标类型,
expression是要转换的表达式,
cast-name是static_cast;dynamic_cast;const_cast;reinterpret_cast中的一个;cast_name指定了将要进行那种转换。
static_cast
任何具有明确定义的类型转换,只要不包含底层const,就可以使用static_cast;
double i = 100.098;
double j = 12.234;
int c = static_cast<double>(i) / j;
const_cast
用于改变运算对象的底层const
int a = 10;
const int *const p = &a;
int* c = const_cast<int*>(p);
*c = 210;
cout << *p;
最终输出 210;
强制获得写的权限
reinterpret_cast
在底层对对象提供重新解释。
dynamic_cast
涉及类和虚函数的转换。