基础
基本概念
- C++定义了:一元运算符和二元运算符
- 除此之外,还定义了作用于三个运算对象的三元运算符
- 函数调用也是一种特殊的运算符
(1)组合运算符和运算对象
- 首先要理解==优先级、结合律以及运算对象的求值顺序==
(2)运算对象转换
(3)重载运算符
(4)左值和右值
- 当一个对象被用作右值时,用的是对象的值
- 当一个对象被用作左值时,用的是对象的身份(内存中的未知)
优先级与结合律
- 括号无视优先级与结合律
- 优先级与结合律有
求值顺序
(1)有4种运算符明确规定了求值顺序
- (&&)、(||)、(?:)、(,)
算术运算符
一元运算符的级别最高,然后是乘除法,最低是加减法
计算结果溢出将导致不可预知的后果
取模(%)运算只支持整数类型
- 在除法运算中,两个运算对象的符号相同则商为正数,否则为负;C++11新标准规定,商一律向0取整(不管正负,直接切除小数部分)
逻辑和关系运算符
- 关系运算符作用于算术类型或指针类型
- 逻辑运算符作用于任何能转换成布尔的类型
(1)与和或运算符
- 注意“与”运算符的左侧想检测原则,右侧不一定会检测
(2)非运算符
(3)关系运算符
- 满足左结合律,所以,只要关系运算符两侧的数据类型会马上转变为布尔值,不能再进行连续比较了
(4)相等性测试和布尔字面值
赋值运算符
- 赋值运算符的左右两个运算对象类型不同,则==右侧运算对象将转换成左侧运算对象==
- C++11允许用花括号来初始化列表
- 转换成左侧运算对象时,所占的空间不能大于目标类型空间
(1)赋值运算满足右结合律
- 靠右的赋值运算符会先完成结合
(2)赋值运算符的优先级较低
- 在条件语句中,通常为赋值运算符部分加上括号
(3)切勿混淆相等运算符和赋值运算符
(4)复合赋值运算符
- += -= %= 等等,只执行一次求值,省去了求值拷贝的赋值
递增和递减运算符
除非必须,否则不用递增运算符的后置版本
(1)在一条语句中混用解引用和递增运算符
auto pbeg=v.begin();
while (pbeg!=v.end()&&*pbeg>=0)
cout<<*pbeg++<<endl;
- 此时,由于后置递增运算符的优先级高于解引用运算符,所以pebg++ 等价于 (pebg++)
- 由于将会返回未增加的副本,所以能够实现,显示第一个值,然后向后移动
(2)运算对象可按任意顺序求值
= 不要将递增运算同时符放在赋值运算符的右边和左边
成员运算访问符
- 点运算符和箭头运算符都可以用来访问成员
- 其中,点运算符获取类对象的一个成员
- 箭头运算符,表达式 ptr->mem 等价于 (*ptr).mem
string s1="a string",*p=&s1;
auto n=s1.size(); //运行string对象s1的size成员
n=(*p).size(); //运行p所指对象的size成员
n=p->size(); //等价于(*p).size()
条件运算符
- 条件运算符(?:)的使用形式:
cond?expr1:expr2
(1) 嵌套的条件运算符
(2) 在输出表达式中使用条件运算符
- 最好在cond表达式处加上括号,因为条件运算符的优先级很低
位运算符
- 位运算符提供检查和设置二进制位的功能
(1)移位运算符( >> 或 << )
unsigned char bits=0233;
bits<<8;
(2)位求反运算符(~)
unsigned char bits=0227;
~bits;
(3)位与、位或、位异或
(4)使用位运算符
- ==第138页==实例
(5)移位运算符
- (<<)移位运算符比的优先级:低于算术运算符、高于关系运算符、赋值运算符、条件运算符
sizeof运算符
- 对char或者类型为ichar的表达式执行sizeof运算,结果得1
- 对引用类型执行sizoof运算得被引用对象所占空间的大小
- 对指针执行sizeof运算得到指针本身的所占空间的大小
- 对解引用指针执行sizeof运算得到指针指向的对象所占空间的大小,指针不需有效
逗号运算符
- 对于逗号运算符来说,首先对左侧的表达式求值,然后将求值结果丢弃掉。逗号运算符真正的结果是右侧表达式的值。如果右侧运算对象是左值,那么最终的求值结果也是左值
类型转换
算术转换
- 整型提升
- 无符号类型的运算对象
- 理解算数转换
其他隐式类型转换
- 数组转换成指针
- 指针的转换
- 整数值0或者字面值nullptr能转换成任意指针类型
- 指向任意非常量的指针能转换成void
- 指向任意对象的指针能转换成const void*
- 转换成布尔类型
- 转换成常量
int i;
const int &j=i; //非常量转换成const int的引用
const int *p=&i; //非常量的地址转换成const的地址
int &r=j,*q=p; //错误,不允许const转换成非常量
- 类类型定义的转换
显式转换
- 命名的强制类型转换,形式:
cast-name<type>(expression)
- 其中,cast-name是:static_cast、dynamic_cast、const_cast、reinterpret_cast
(1)static_cast
double slope=static_cast<double>(j) / i;
void* p=&d;
double *dp=static_cast<double*>(p);
(2)const_cast
- 只能改变运算对象的底层const
const char *pc;
char *p=const_cast<char*>(pc);
(3)reinterpret_cast
- 为运算对象的位模式提供较低层次上的重新解释
int *ip;
char 8pc=reinterpret_cast<char*>(ip);
- 旧的强制类型转换
- type(expr); //函数形式的强制类型转换
- (type)expr; //C语言风格的强制类型转换