表达式
取地址&,解引用*,都是运算符,只不过这叫一元运算符。
左值和右值
以前的理解是能作为等号左边的就是左值,能放在等号右边的就是右值。那是C语言。C++中不一样,比如常量对象,不能放在等号左边,但是他是左值。C++中应该这样理解:当一个对象被用作右值的时候,用的是对象的值(内容);当对象被用作左值的时候,用的是对象的身份(在内存中的位置)。
算术运算符+(正),-(负),*,/,%,+,-
bool b = true;
bool b2 = -b; // b2是true
%:参与取余运算的运算对象必须是整数类型。且如果m%n不等于0,则它的符号和m相同:
-21 % -8 == -5
21 % -5 == 1
逻辑和关系运算符!,<,<=,>,>=,==,!=,&&,||
短路求值:当且仅当逻辑运算符的左侧对象无法确定表达式结果时才会计算右侧运算对象的值。
赋值运算符=
赋值运算符=的结果是它左侧运算对象。所以才可以连等:
int ival, jval;
ival = jval = 0;
C++11允许列表初始化,也就是用花括号。如果等号左侧运算对象是内置类型,那么初始列表最多只能包含一个值,而且该值即使转换的话其所占空间也不应该大于目标类型的空间。
错误例子: int k = {3.14};
赋值运算符优先级低,很多情况下往往要加括号:
int i;
while((i = get_value()) != 42)
{...}
/*
上面的写法比下面这种好:
int i = get_value();
while(i != 42){
i = get_value();
}
*/
递增和递减运算符++,--
后置递增运算符的优先级高于解引用运算符:*pbeg++不用加括号,相当于*(pbeg++)
条件运算符?:
cout << ((grade < 60) ? “fail” : “pass”); //输出pass或fail
cout << (grade < 60) ? “fail” : “pass”; //输出1或0
cout << grade < 60 ? “fail” : “pass”; //错误,试图比较cout和60
移位运算符<<, >>(左移运算符<<在右侧插入值为0的二进制位。右移运算符>>依赖于左侧的对象,如果左侧是无符号类型,在左侧插入0,如果左侧是带符号类型,插入符号位副本或值为0的二进制位。)
求反运算符~位与、位或、位异或运算符&,|,^
sizeof运算符
逗号运算符,
类型转换
表达式中既有整数类型又有浮点数类型的运算对象,整型会转换成浮点型。
整型提升:把小整数类型转换成较大的整数类型
显式转换:static_cast,dynamic_cast,const_cast,reinterpret_cast
int i, j;
double slope = static_cast<double>(j)/i;
static_cast还可以用来找回存在于void*指针:
void* p = &d;
double *dp = static_cast<double*>(p);
const_cast可以将常量对象转换成非常量对象,即去掉const性质。不能用它改变表达式的类型。
const char *pc;
char *p = const_cast<char*>(pc);
错误:
const_cast<string>(pc)