由多个运算对象组成,对表达式求值将得到一个结果。如字面值及变量,和运算符组合起来就是较为复杂的表达式。
基础 一元运算符和二元运算符一元运算符:作用于一个运算对象
二元运算符:作用于两个运算对象
存在三元运算符,函数调用也是一种特殊的运算符,对运算对象数目无要求。
如果两种类型有关联,需要其中一种类型的运算对象时,可以用另一种关联类型对象或值来替代,二者可以相互转换。
隐式转换- 类型转换自动执行,不需要程序员介入。
- 算数转换
整型提升:把小整数转换成较大的整数。对于无符号类型,需要进行整型提升,再将小符号转换成较大的类型。
数组变指针:使用数组名,将自动转换成指向数组首元素的指针。当使用decltype、取地址(&)、sizeof和typeid时,上述转换不会发生。
指针转换:0/nullptr能转成任意类型指针,任意非常量指针能转换成void*,指向任意对象的指针能转换成 const void*。
布尔转换:判断语句(if/while)
常量转换:非const到const
类类型
- 旧式强转换模式
type(expr)
(type)expr
- 对象显式强制转换,命名强制类型转换
cast-name(expression);
- cast-name
static_cast:不包含底层const时使用,可以用来强制转换类型,或者找回存在于void*中的指针。
int a = 1; double b = static_cast(a); int* p = &a; void* vp = p; int *ip = static_cast (vp); //vp中类型必须是int*
const_cast:只改变对象的底层const
int a = 2; const int c = 10; const int* p1 = &c; int* p2 = const_cast(p1); cout << *p2 << endl; //10 *p2 = 1; cout << *p2 << endl; //1 cout << *p1 << endl; //1 p2 = &a; cout << *p2 << endl; //2
reinterpret_cast:为运算对象为模式提供较低层次上的重新解释。(不推荐使用)
dynamic_cast:
运算符作用于类类型运算对象时,用户可以自定义其含义,为已存在运算符赋予另一层含义,称为重载运算符。
eg:IO库里的“>>”和“<<”,压入压出,逻辑运算里是右移和左移。
- 右值用的是对象的值(内容),左值用的是对象的身份(在内存中存在的地址)。
- 需要右值的地方可以用左值代替,实际使用的是它的值(内容)。
int *p; decltype(*p) //解引用是左值,地址是p的地址,返回类型int& decltype(&p) //返回p的地址,取地址符生成右值,内容是指向整形指针的指针,返回类型是int**运算符优先级、结合律
优先级:高优先级使对象更紧密组合在一起。
结合律:优先级相同,组合规则由结合律确定。
括号无视优先级和结合律 。
运算优先级表:
C++运算符优先级
大多数情况下,不会指明求值顺序,且求值顺序和优先级结合律无关。考虑到这个问题,如果运算过程中改变了某个运算对象的值,在表达式其他地方不要再使用这个对象。除非求值顺序已知。
int i= f1()*f2(); //无法知道f1()和f2()谁先被调用运算符 1.算术运算符
- 优先级:一元“+”“-” > “*”“/”“%” > “+”“-”
- 算术运算符运算对象和求值结果都是右值。
- 对于布尔类型运算:
bool f = 0; bool f2 = -f; //f2为0 bool f3 = !f; //f3为1
- 对于负数商:(-m)/n= m/(-n) = -(m/n)
- 对于负数余数:m%(-n) = m%n, (-m)%n=(-m)%(-n)=-(m%n)
- 优先级:逻辑非(!)>比较(>,<,>=,<=)>相等(==,!=)>逻辑与(&&)>逻辑或(||)
- 运算对象和求值结果都是右值。
- 对于逻辑与和逻辑或,“&&”和“||”具有短路求值策略。对于与,左侧为真才判断右侧;对于或,左侧为假才判断右侧。左侧运算是为了保证右侧运算对象求值过程的正确性和安全性。
- 比较运算符:返回布尔值
- 优先级:关系运算符>赋值运算符
- 左侧运算对象是可修改左值,结果是左值,类型是左侧运算对象的类型。
- 赋值运算符满足右结合律
int i,j; i = j = 0; //三者类型相同,或者可以类型转换
- 复合赋值:普通运算符求值两次,复合运算符求值一次。
a += b;4.递增递减运算符
++i; --i; //前置版本
i++; i--; //后置版本
- 除非必须,不使用后置版本。当既想将对象加一或减一,又想引用它原来的值时,用后置版本。
- 点运算符和箭头运算符
- 解引用运算符优先级低于点运算符
p->mem; (*p).mem;6.条件运算符
- 条件运算符
cond?expr1:expr2;
- 嵌套条件运算符:嵌套最好不要超过2~3层
cond1?expr1:cond2?expr2:expr3
- 条件运算符优先级非常低,使用时通常需要加括号。
cout<<((grade<60)?"fail":"pass")<7.位运算符 8.sizeof运算符
- 用于整形类型对象,把对象看作二进制位集合
- 优先级:位取反(~)>左右移(>>,<<)>位与(&)>位亦或(^)>位或(|)
- 对于符号位的位运算取决于机器,所以建议仅将位运算符用于处理无符号整型
- 返回一条表达式或一个类型名字所占字节数。满足右结合律。所得类型size_t类型常量表达式。
sizeof(type) sizeof expr //返回表达式结果类型大小
- 使用起来和deltype很像,sizeof不实际计算运算对象的值。所以对于类成员,不需要提供一个具体对象,就能获得类成员大小。
int a = 1; int* p; int& refa = a; cout << sizeof(a) << endl; //int型大小,4 cout << sizeof(p) << endl; //int型指针大小,8 cout << sizeof(*p) << endl; //int型大小,4 cout << sizeof(refa) << endl;//int型大小,4 char b = '9'; cout << sizeof(b) << endl; //char型大小,1 int c[] = { 1,2,3,4,5 }; cout << sizeof(c) << endl; //数组大小,4*5 = 20 char e[] = { 'h','h','d','y','z','w','h','y',' '}; cout << sizeof(e) << endl; //9 cout << strlen(e) << endl; //8,不算空格 string s = "hhdyzwhy"; cout << sizeof(s) << endl;//string类型固定部分大小,40 vector9.逗号运算符d = {1}; cout << sizeof(d) << endl;//vector类型固定部分大小,32 for(int i = 0;i



