前言一、递增递减运算符
1.副作用和顺序点2.递增/递减运算符和指针3.组合赋值运算符 二、逗号运算符三、关系表达式
1.C风格字符串的比较2.比较string类字符串
前言四则运算符请查看文章《C++知识点整理: 04算数表达式》
一、递增递减运算符
++ 运算符是递增运算符,它将操作数进行+1,我们可以用i++来替代i = i + 1;它常用于循环操作中:将循环计数+1。
++运算符有两种变体,作为前缀位于操作数的前面,++i,还有作为后缀位于操作数的后面,i++。
–i和i–同++运算符一般。
注意 : 两者变体对操作数的影响是一样的,但是影响的时间不同
a++
int num1,a = 0; num1 = a++; cout << num1 << endl; cout << a << endl;
运行后结果如下:
0 1
++a
int num2,a = 0; num2 = ++a; cout << a << endl; cout << num2 << endl;
代码运行结果如下:
1 1
粗略的讲,a++意味着使用a的当前值计算表达式,然后将a的值加1;而++a的意思是先将a的值加1,然后使用新的值来计算表达式。
1.副作用和顺序点副作用是指:在计算表达式时对某些东西进行了修改。
顺序点是指:程序过程中的一个点,在这里,进入下一步之前将去报对所有的副作用都进行了评估。在C++中,分号**;**就是一个顺序点,程序在处理下一条语句之前,赋值运算符、递增运算符和递减运算符执行的所有修改都必须完成。
每一个完整表达式末尾都是一个顺序点
while(i++ < 9){
cout << i << endl;
};
在上述代码中,在完成i++<9的判断后,打印i的值,那么此时被打印出来的i值是原先的值还是被加1后的值?
答案是加1后的值,因为i++<9是一个完整的语句表达式,因为他是while循环的测试条件,因此该表达式的末尾是一个顺序点。所以,C++确保副作用(将i加1)在程序进入cout之前完成。
y = (6 + x++) + (8 + ++x);
在上述代码中,由于(6 + x++)并不是一个完整的表达式,因此,C++不保证x的值在计算表达式(6 + x++)后立刻增加1,在这条语句中,整个式子才是一个完整的表达式,而分号标示了顺序点,因此C++只保证程序执行到下一条语句之前,x的值被递增两次,所以,应该避免使用这样的表达式
两者的区别
在循环语句中,或者其他使用完整表达式的情况下,++a和a++没有什么区别,但我们应该尽可能的使用前缀。
对于++a来说,程序将a的值加1 ,然后返回结果
对于a++来说,程序首先复制一个副本,将其加1,然后将复制的副本返回。
所以,使用前者的效率更高
2.递增/递减运算符和指针将递增运算符用于指针的时候,将把指针的值增加其指向的数据类型的字节数。
优先级:
前缀递增、前缀递减和解除引用运算符的的优先级相同,以从右到左的方式进行结合
后缀递增和后缀递减的优先级相同,但比前缀运算符的优先级高,这两个运算符以从左到右的的方式进行结合
double arr[3] = {6,8,9};
double * pt = arr;
double x = *++pt;
cout << x << endl;
前缀运算符由于从右到左的方式进行结合,意味着:*++pt先将++应用于pt,然后将*号应用于被递增后的pt,所以结果为8
double x = ++ *p; cout << x << endl;
上述代码意味着先取得pt指向的值,然后将这个值加1;
在这种情况下,pt的指向依旧不变。
double x = *pt++; cout << x << endl;
后缀运算符++的优先级更高,意味着,首先进行pt的加1,将指针指向下一个,而不是pt,然而后缀运算符意味着将对原来的地址而不是递增后的新地址解除引用,因此pt++的值为指向原先的值,但该语句执行完毕后,pt的值将指向下一个地址。
3.组合赋值运算符int num1 = 0; int num2 = 1; num1 += num2;
C++合并了加法和赋值操作的运算符,能够更简洁的操作代码。
+=运算符将两个操作数相加,并将结果赋给左边的操作数。
| 操作符 | 作用 |
|---|---|
| += | 将两者相加的值赋予左边的操作数 |
| -= | 将两者相减的值赋予左边的操作数 |
| *= | 将两者相乘的值赋予左边的操作数 |
| /= | 将两者相除的值赋予左边的操作数 |
| %= | 将两者求余后的值赋予左边的操作数 |
逗号运算符对表达式允许将两个表达式放到C++句法只允许放一个表达式的地方。
在创建变量时,我们可以通过使用逗号运算符来使得在同一个表达式中创建两个变量。
int num1; int num2,num3;
但要注意的是,在赋值时,赋值运算符只能给其中一个操作数进行赋值。
int num1,num2 = 0; cout << num1 << "and" << num2 << endl;
上述代码会报错,原因是num1未被初始化。在赋值过程中,编译器会认为上述代码的意思是,创建一个变量num1,不进行初始化,然后再创建一个变量num2,并将0赋予num2。
int num1 = 1,num2 = 2; cout << num1 << "and" << num2 << endl;
结果为:1and2。
C++确保先计算第一个表达式,然后计算第二个表达式,换句话说,实际上逗号运算符就是一个顺序点,
//创建变量i,并将6赋予i,之后创建一个变量,将i + 1的值赋予j。 //由于在赋值之前已经创建了变量i,所以在j = i + 1的表达式中,i的值是明确的。 int i = 6 ,j = i + 1;
其次,在所有运算符中,逗号运算符的优先级最低
i = 6,8; //上述代码将被解释为: (i=6),8;
也就是说,将i的值设为6,数值8将毫无意义,然后,由于括号的优先级最高,在括号内,首先执行逗号右侧的表达式值。
i = (6,8);
结果为8.
在for循环语句中,控制部分的更新部分中也可以使用逗号运算符,使其两个表达式合并为一个。
for(int i = 0,j = 0; i < 9 ;i++,j++) ;三、关系表达式
C++提供了6中关系运算符来对数字进行比较,由于字符用ASCII码表示,因此也可以将这些字符用于关系表达式,,不过不能用于C风格的字符串,但可以用于string类对象,当结果为真,则赋予true值,否则为false。
| 操作符 | 含义 |
|---|---|
| < | 小于 |
| <= | 小于或等于 |
| == | 等于 |
| > | 大于 |
| >= | 大于或等于 |
| != | 不等于 |
关于优先级,关系运算符的优先级要低于算术运算符。
x + 6 > y + 8;
上述代码的翻译如下:
(x + 6) > (y + 8);
当然,下述代码虽然为错误翻译,但其表达式是有效的
x + (6 > y) + 8;
由于这是一个算术表达式,编译器会将6 > y的bool值提升为int,true为1,false为0,提升后的Int值将继续进行运算。但我们往往并不希望这样。
1.C风格字符串的比较char ch[] = "Hello"; int i = (ch == "Hello");
在上述代码中,结果为0,因为数组名代表的是数组的地址,同样,用括号引起来的字符串也是地址,所以上述的代码实际是在判断两者的地址是否相同。
所以,想要进行两个字符串的比较,应该使用函数strcmp()来进行比较。
该函数接受两个字符串地址作为参数,这意味着参数可以是指针、字符串常量或者数组名。
如果两个字符串相同,则该函数返回一个0;该函数是通过按字母顺序(也就是系统编码)来进行比较。
当第一个字符串按字母顺序排在第二个字符串之前,则返回一个负数,之后则返回一个整数。
如果想要使用string类字符串来比较,将比C风格字符串更加简单,因为string类中已经做好了相关的关系运算符的重载,在两个string类字符串进行关系比较时,将进行字符串的比较,而不是地址的比较。
string str1 = "Hello"; string str2 = "Tricker"; int i = str1 == str2; cout << i << endl;
string关系运算符的重载意味着,不止两个string类进行比较时直接比较字符,其中一个为string类对象时,就可以调用string重载后的关系运算符



