表达式
左值与右值
左值可以用作右值,但右值不能用作左值。左值用的是对象的身份,即内存地址,而右值用的是对象的内容,即值。
因此,左值不能为常量。
除取地址符返回的指针是右值,其他的运算符返回的基本都是左值。
对于decltype来说,如果是左值,则为引用,如果是右值,则为指针。
求值顺序
对于运算符所操作的对象,并没有定义运算顺序,也并非是从左到右的,如果出现了这种情况,且会由于顺序而对结果造成影响,则称表达式为未定义的。
只有***&& || ?: ,四种运算符指定了求值顺序***。
算术运算符
正负号乘除取余加减
返回的都是右值。
当混合运算时,小整数类型(bool,char,short)会自动转换为大整数类型(int)。
int会转为float/double。(并不知道具体是哪一个)
商一律切除小数部分。
当m时负值时,结果也为负值。
逻辑运算符
非大小判断等于判断与或
当一个变量非常大时,遍历时使用引用能避免大量拷贝操作。
赋值运算符
右结合律,因此可以连等。
优先级较低。
递增与递减
前置版本返回左值,后置版本返回右值。
前置:加完后返回值
后置:加完后返回原始值
最好使用前置
解引用
解引用低于递增递减。
****ptr++***是返回当前值再向后移一位。
点与箭头运算符
点:其所属对象是左值还是右值决定成员
箭头:左值
判断
cond ? A : B
A与B也可以是表达式。
位运算
取反(~)左右移与亦或或
最好不要用左右移来处理有符号数,对于符号位的处理是未定义的。
左右移的底层是在其左右添加新的位,但右移在处理有符号数时视情况而定。
但是实际在Dev中使用时并不会因为左移而去掉符号。
在位处理时,小整数类型会被提升为大整数。
有趣的是,unsigned int在取反后仍然是unsigned int,并没有提升到int,但是unsigned char却被提升为了int
IO
cout的返回值是cout,当输出cout的时候会输出一个地址,应该是cout的地址(?),并且地址不变,即便电脑不同,也都不变。
左结合律。
算术IO关系赋值条件
sizeof
sizeof(类型/变量),返回类型是size_t,常量值。
在获取大小的时候不会去获得其具体值,因此可以解空指针引用。
且可以不通过实例来通过作用域获取类的成员的大小。
char是一个字节。
引用不是对象,因此获取其的大小是获取它所引用对象的大小。
指针是对象,因此获取的是指针的大小。
指针是可以直接被赋予常量地址的,即实际值,只需要将这一表达式转换为***int ****即可。
可以用来获取数组的大小。
逗号
逗号返回的是最右侧表达式的返回值。
整型提升
- 将小整数类型提升为大于int的最小的整数类型(unsigned intint)。
- 若为不同符号类型(下面的大于小于是指存储空间大小)
- 有符号小于无符号,有符号将转为无符号。(更常见,但若有符号为负数,则结果将错误)
- 有符号大于无符号,无符号将转为有符号。
在进行整型提升之后,才会进行类型转换。
当cin读入时,若成功,则返回一个地址,与cout一致,不然返回0。
数组与指针有着本质的不同,将数组赋给指针的时候,实际上执行了类型转换。
强制类型转换
用法:转换方式<类型>(变量)。
-
const_cast,可以将常量转为非常量。
常用于函数重载。
-
static_cast,普通的强制类型转换,可以将无视损失精度而进行转换。对于原本不能进行互相转换的类型可以通过***void ****作为中转来转换。
-
reinterpret_cast,直接将其存储内容按位重新解释为转换后的类型,并没有对其值本身作任何更改,因此对于原本不能进行互相转换的类型可以直接进行转换。
-
dynamic_cast,后面会谈及。
static_cast与reinterpret_cast的具体区别及4种cast的用法可参考:
static_cast ,reinterpret_cast - 猿人谷 - 博客园
旧式类型转换会先尝试const_cast与static_cast,若不合法,再执行reinterpret_cast。