左值和右值: 一个表达式要么是左值要么是右值。左值可以放在赋值号的左边,强调变量可以保存值的属性。右值不能放在赋值号的左边,强制的是值。左值可以当右值用,反过来就不行。
表达式的值受到运算符的优先级、结合律的影响,严格来说还会受到求值顺序的影响,但是因为C++标准没有规定大多数运算符的求值顺序(逻辑运算符是规定量的,“短路求值”的策略),所以应该避免这种情况。
比如 int a=g()*f();这种情况要保证g()和f()不修改同一个变量,就是要保证不管先调用哪个函数,a的值应该都是一样的。
C++标准规定商一律向0取整,就是说直接截断小数部分。重点注意取模操作,m%(-n)等于m%n,(-m)%n等于-(m%n).
赋值运算符是右结合的。就是说int a=b=c=8之后,abc的值都是8,先c=8再b=c最后a=b.
位运算作用于负数的行为是未定义的,最好只用于无符号数。
sizeof 作用于指针的解引用时,并不会真的解引用,因此可以是无效指针。
sizeof decltype 引用 作用于数组名字的时候,数组名字都不会转换成指针,所以可以使用sizeof得到整个数组的大小,再除以单个元素的大小就能得到数组的长度。
,逗号也是一个二元运算符,先对左侧操作数求值,然后丢弃,然后对右操作数求值并返回。
一个表达式在计算时,会先将表达式的操作数类型统一,如果操作数的类型不一致那就像数据宽度最宽的那个看齐。
数组名字到指针的转换是隐式发生的,当作用于decltype和取地址&和sizeof和typeid时转换不会发生。
显式的类型转换有static_cast和dynamic_cast和const_cast和reinterpret_cast转换。
一般的转换用static_cast,比如double到int,int和char之间。
const_cast用于取消const属性,比如
int main() {
const char*a="123";
char*wt=const_cast<char*>(a);
wt[0]='A';
cout<<a<<std::endl;
return 0;
}
这个程序可以正常运行,但是行为是未定义的,比如目前在我电脑上这个程序就啥也不输出。
reinterpret_cast用于指针类型的转换,就是把char转换成int这种。
旧式的转换会根据情况转换成上面的转换,把具体的转换写出来可以增加程序的可读性。
运算符优先级表,没事记一记,两张图是一张表,短的那部分是头。