1.注意赋值运算优先级比较低,一定要注意加括号
另外我的常犯的错:对于i=j=0,这句话等价于j=0,i=j;也就是赋值运算的返回值正是赋的那个值,我总以为是赋值成功返回1
一下两种写法都对,第二种解法更简洁直白,但是注意赋值运算优先级较低,需要加上括号 int i=get_value(); while(i!=42){ i=get_value(); //... } int i; while((i=get_value())!=42){ //... }
2.递增递减的前置后置运算:若非必须,一般不用后置版本的运算,原因如下:
1)后置版本需要将原始值存下来用于返回,如果不需要修改前的值,那么后置版本的操作就是一种浪费
2)对于整数和指针编译器可能会进行一定的优化;但是对于复杂类型的迭代器来说,这种额外操作可能消耗巨大
int i=0,j; j=++i; //j=1,i=1:前置版本得到递增之后的值 j=i++; //j=1,i=2:后置版本得到递增之前的值
3.自增运算的常用写法:*iter++,自增运算优先级比解引用优先级高,另外解引用优先级低于点运算优先级
4.条件三目运算符可以使用嵌套的
final_grade = (grade > 90) ? "high pass" : (grade < 60) ? "fail" : "pass";
5.强制类型转换的三种(这三个运算符记得后面跟的对象要加括号,其实还有一种dynamic_cast)
static_cast:只要不包含底层const,都可以使用
//进行强制类型转换以便执行浮点数除法 double slope = static_cast<double>(j)/i; //任何非常量对象地址都能存入void* void *p=&d; //转换为double* double *dp=static_cast<double*>(p);
const_cast:只能改变运算对象的底层const(底层const即指针所指的对象是常量),const_cast能且只能改变对象的常量属性,常常用于有函数重载的上下文中
经典例子:企图改变常量值失败,得到指针值一样,但是指针所指的对象的值不一样
const char* pc; char *p=const_cast<char*>(pc); //正确,但是通过p写值是未定义的行为 //一个例子,很奇怪的做法,最终q和p是一样的,但是其所指的内容的值是不一样的 const int a=5; const int *p=&a; int *q=const_cast<int *>(p); *q=6; cout<<*q<<" "<<a<<endl; //输出:6 5 cout<<q<<" "<<p<<endl; //输出:二者一样
reinterpret_cast:通常对运算对象的位模式提供较低层次上的重新解释,这个风险较大
int *ip; //虽然pc的声明是字符类型指针,但实际上pc指向的对象为int而非char char *pc=reinterpret_cast<char *>(ip); //错误 string str(pc);