C++官网参考链接:Operators - C++ Tutorials (cplusplus.com)
操作符
一旦介绍了变量和常量,我们就可以使用操作符来操作它们。下面是操作符的完整列表。在这一点上,可能没有必要了解所有的方法,但这里列出的所有方法也可以作为参考。
赋值操作符(=)
赋值操作符给变量赋值。
x = 5;
这条语句将整数值5赋值给变量x。赋值操作总是从右到左进行,而不是从左到右:
x = y;
这条语句将变量y中包含的值赋给变量x。执行这条语句时,x的值将丢失,并由y的值替换。
还要考虑到,在执行赋值操作时,我们只将y的值赋给x。因此,如果y在稍后发生变化,并不会影响x取的新值。
例如,让我们看看下面的代码——我已经把存储在变量中的内容的演变作为注释:
// assignment operator
#include <iostream>
using namespace std;
int main ()
{
int a, b; // a:?, b:?
a = 10; // a:10, b:?
b = 4; // a:10, b:4
a = b; // a:4, b:4
b = 7; // a:4, b:7
cout << "a:";
cout << a;
cout << " b:";
cout << b;
}
该程序在屏幕上打印a和b的最终值(分别为4和7)。请注意,尽管我们之前声明了a=b,但a并没有受到b最终修改的影响。
赋值操作是可以求值的表达式。这意味着赋值本身有一个值,并且对于基本类型---这个值是在操作中被赋值的那个。例如:
y = 2 + (x = 5);
在这个表达式中,y被赋值为另一个赋值表达式的值(该表达式本身的值为5)加2的结果。它大致相当于:
x = 5;
y = 2 + x;
将7赋值给y的最终结果。
下面的表达式在C++中也是有效的:
x = y = z = 5;
它给所有三个变量赋值为5:x、y和z;总是从右到左。
算术操作符(+、-、*、/、%)
C++支持的五种算术操作是:
operator | description |
---|---|
+ | addition(加法) |
- | subtraction(减法) |
* | multiplication(乘法) |
/ | division(除法) |
% | modulo(求模) |
加法、减法、乘法和除法的操作对应于它们各自的数学操作符。最后一个是用百分号(%)表示的求模操作符,它给出两个值除法的余数。例如:
x = 11 % 3;
结果变量x包含值2,因为11除以3得到3,余数为2。
复合赋值(+=、-=、*=、/=、%=、>>=、<<=、&=、^=、|=)
复合赋值操作符通过对变量执行操作来修改变量的当前值。它们相当于将操作的结果赋值给第一个操作数:
expression(表达式) | equivalent to...(等价于) |
---|---|
y += x; | y = y + x; |
x -= 5; | x = x - 5; |
x /= y; | x = x / y; |
price *= units + 1; | price = price * (units+1); |
所有其他复合赋值操作符也是如此。例如:
// compound assignment operators
#include <iostream>
using namespace std;
int main ()
{
int a, b=3;
a = b;
a+=2; // equivalent to a=a+2
cout << a;
}
递增和递减(++、--)
有些表达式还可以进一步简化:递增操作符(++)和递减操作符(--)对存储在变量中的值递增或递减1。它们分别等价于+=1和-=1。因此:
++x;
x+=1;
x=x+1;
在功能上都是相同的;它们三个的x值都增加了1。
在早期的C编译器中,前面的三个表达式可能会根据所使用的表达式产生不同的可执行代码。现在,这种类型的代码优化通常由编译器自动执行,因此这三个表达式应该产生完全相同的可执行代码。
这个操作符的一个特点是它既可以用作前缀,也可以用作后缀。这意味着它可以写在变量名(++x)之前,也可以写在变量名(x++)之后。虽然在像x++或++x这样的简单表达式中,两者的意思完全相同;在计算递增或递减操作结果的其他表达式中,它们的含义可能有重要的不同:在递增操作符用作值的前缀(++x)的情况下,表达式计算为x的最终值,因为它已经递增。另一方面,如果将它用作后缀(x++),x的值也会增加,但表达式的计算结果为x增加之前的值。注意区别:
Example 1 | Example 2 |
---|---|
x = 3; | x = 3; |
在Example 1中,赋给y的值是x增加后的值。而在Example 2中,它是x增加之前的值。
关系和比较操作符(==、!=、>、<、>=、<=)
可以使用关系操作符和相等操作符比较两个表达式。例如,知道两个值是相等还是一个大于另一个。
该操作的结果为true或false(即布尔值)。
C++中的关系操作符有:
operator | description |
---|---|
== | Equal to(等于) |
!= | Not equal to(不等于) |
< | Less than(小于) |
> | Greater than(大于) |
<= | Less than or equal to(小于或等于) |
>= | Greater than or equal to(大于或等于) |
这里有一些例子:
(7 == 5) // evaluates to false
(5 > 4) // evaluates to true
(3 != 2) // evaluates to true
(6 >= 6) // evaluates to true
(5 < 5) // evaluates to false
当然,可以比较的不仅仅是数值字面量,而是任何值,当然也包括变量。设a=2,b=3,c=6,则:
(a == 5) // evaluates to false, since a is not equal to 5
(a*b >= c) // evaluates to true, since (2*3 >= 6) is true
(b+4 > a*c) // evaluates to false, since (3+4 > 2*6) is false
((b=2) == a) // evaluates to true
小心!赋值操作符(操作符=,有一个等号)与相等比较操作符(操作符==,有两个等号)不同;第一个(=)将右边的值赋给左边的变量,而另一个(==)比较操作符两边的值是否相等。因此,在上一个表达式((b=2)==a)中,我们首先将值2赋给b,然后将其与a(它也存储值2)进行比较,得到true。
逻辑操作符(!、&&、||)
操作符!是对应于布尔操作非的C++操作符。它只有一个操作数,对于在其右侧的值,并将其反转,如果操作数为true,则产生false;如果操作数为false,则产生true。基本上,它返回与计算操作数相反的布尔值。例如:
!(5 == 5) // evaluates to false because the expression at its right (5 == 5) is true
!(6 <= 4) // evaluates to true because (6 <= 4) would be false
!true // evaluates to false
!false // evaluates to true
当对两个表达式求值以获得单个关系结果时,使用逻辑操作符&&和||。操作符&&对应于布尔逻辑操作与,如果其两个操作数都为true,则为true,否则为false。下面的面板显示了操作符&&对表达式a&&b求值的结果:
&& OPERATOR (and) | ||
---|---|---|
a | b | a && b |
true | true | true |
true | false | false |
false | true | false |
false | false | false |
操作符||对应于布尔逻辑操作或,如果其操作数有一个为true,则产生true,因此只有当两个操作数都为false时才为false。以下是a||b的可能结果:
|| OPERATOR (or) | ||
---|---|---|
a | b | a || b |
true | true | true |
true | false | true |
false | true | true |
false | false | false |
例如:
( (5 == 5) && (3 > 6) ) // evaluates to false ( true && false )
( (5 == 5) || (3 > 6) ) // evaluates to true ( true || false )
在使用逻辑操作符时,C++只从左到右求出组合关系结果所需的值,忽略其余的值。因此,在上一个例子((5==5)||(3>6))中,C++首先计算5==5是否为true,如果是,它从不检查3>6是否为true。这就是所谓的短路计算,它的工作原理如下:
operator(操作符) | short-circuit(短路求值) |
---|---|
&& | if the left-hand side expression is (如果左边的表达式为false,则组合结果为false(右边的表达式永远不会计算)。) |
|| | if the left-hand side expression is (如果左边的表达式为true,则组合结果为true(右边的表达式永远不计算)。 ) |
当右边的表达式有副作用,比如改变值时,这一点尤为重要:
if ( (i<10) && (++i<n) ) { /*...*/ } // note that the condition increments i
这里,组合条件表达式将i加1,但只有在&&左边的条件为true时才会进行,否则右边的条件(++i<n)永远不会被执行。
条件三元操作符(?)
条件操作符计算一个表达式,如果该表达式计算为true,则返回一个值,如果表达式计算为false,则返回另一个值。它的语法是:
condition ? result1 : result2
如果condition为true,则整个表达式的计算结果为result1,否则为result2。
7==5 ? 4 : 3 // evaluates to 3, since 7 is not equal to 5.
7==5+2 ? 4 : 3 // evaluates to 4, since 7 is equal to 5+2.
5>3 ? a : b // evaluates to the value of a, since 5 is greater than 3.
a>b ? a : b // evaluates to whichever is greater, a or b.
例如:
// conditional operator
#include <iostream>
using namespace std;
int main ()
{
int a,b,c;
a=2;
b=7;
c = (a>b) ? a : b;
cout << c << '\n';
}
在本例中,a为2,b为7,因此正在计算的表达式(a>b)不为true,因此在问号后指定的第一个值被丢弃,而选择第二个值(冒号后的值)也就是b(值为7)。
逗号操作符(,)
逗号操作符(,)用于分隔只包含一个表达式里的两个或多个表达式。当必须对一组表达式求值时,只考虑最右边的表达式。
例如,以下代码:
a = (b=3, b+2);
首先将值3赋给b,然后将b+2赋给变量a。因此,最后,变量a将包含值5,而变量b将包含值3。
按位操作符(&、|、^、~、<<、>>)
按位操作符修改变量时要考虑表示变量所存储值的位模式。
operator | asm equivalent | description |
---|---|---|
& | AND | Bitwise AND(按位与) |
| | OR | Bitwise inclusive OR(按位或) |
^ | XOR | Bitwise exclusive OR(按位异或) |
~ | NOT | Unary complement (bit inversion)(一元互补) |
<< | SHL | Shift bits left(位左移) |
>> | SHR | Shift bits right(位右移) |
显式类型强制转换操作符
类型强制转换操作符允许将给定类型的值转换为另一种类型。在C++中有几种方法可以做到这一点。最简单的一种是从C语言继承来的,它位于要转换的表达式之前,由括号(())括起来的新类型转换:
int i;
float f = 3.14;
i = (int) f;
前面的代码将浮点数3.14转换为整数值(3);剩下的小数部分就丢失了。这里,类型强制转换操作符是(int)。在C++中做同样事情的另一种方法是在要被类型转换的表达式前面使用函数表示法,并将表达式括在圆括号之间:
i = int(f);
强制转换类型的两种方式在C++中都是有效的。
sizeof
该操作符接受一个形参,可以是类型,也可以是变量,并以字节为单位返回该类型或对象的大小:
x = sizeof(char);
在这里,x被赋值为1,因为char类型的大小为一个字节。
sizeof返回的值是一个编译时常量,因此它总是在程序执行之前确定。
其它操作符
在本教程的后面部分,我们将看到更多的操作符,比如指向指针或面向对象编程的具体操作符。
操作符的优先级
一个表达式可以有多个操作符。例如:
x = 5 + 7 % 2;
在C++中,上面的表达式总是将6赋值给变量x,因为%操作符的优先级高于+操作符,并且总是在前面求值。表达式的某些部分可以用圆括号括起来,以覆盖此优先顺序,或显式地明确预期的效果。注意区别:
x = 5 + (7 % 2); // x = 6(same as without parenthesis)
x = (5 + 7) % 2; // x = 0
C++操作符的优先级从高到低的顺序如下:
Level(级别) | Precedence group(优先级组) | Operator(操作符) | Description(描述) | Grouping(分组) |
---|---|---|---|---|
1 | Scope(作用域) | :: | scope qualifier(作用域限定符) | Left-to-right |
2 | Postfix (unary) (后缀(一元)) | ++ -- | postfix increment / decrement(后缀递增/递减) | Left-to-right |
() | functional forms(函数形式) | |||
[] | subscript(下标) | |||
. -> | member access(成员访问) | |||
3 | Prefix (unary) (前缀(一元)) | ++ -- | prefix increment / decrement(前缀递增/递减) | Right-to-left |
~ ! | bitwise NOT / logical NOT (按位非/逻辑非) | |||
+ - | unary prefix(一元前缀) | |||
& * | reference / dereference (引用/解引用) | |||
new delete | allocation / deallocation (分配/释放) | |||
sizeof | parameter pack(参数包) | |||
(type) | C-style type-casting (C风格类型强制转换) | |||
4 | Pointer-to-member (指向成名的指针) | .* ->* | access pointer(访问指针) | Left-to-right |
5 | Arithmetic: scaling (算术:按比例缩放) | * / % | multiply, divide, modulo (乘,除,求模) | Left-to-right |
6 | Arithmetic: addition (算术:加法) | + - | addition, subtraction (加,减) | Left-to-right |
7 | Bitwise shift(位移动) | << >> | shift left, shift right (位左移,位右移) | Left-to-right |
8 | Relational(关系) | < > <= >= | comparison operators (比较操作符) | Left-to-right |
9 | Equality(等于) | == != | equality / inequality (等于/不等于) | Left-to-right |
10 | And(按位与) | & | bitwise AND(按位与) | Left-to-right |
11 | Exclusive or(按位异或) | ^ | bitwise XOR(按位异或) | Left-to-right |
12 | Inclusive or(按位或) | | | bitwise OR(按位或) | Left-to-right |
13 | Conjunction(结合) | && | logical AND(逻辑与) | Left-to-right |
14 | Disjunction(分离) | || | logical OR(逻辑或) | Left-to-right |
15 | Assignment-level expressions (赋值级别表达式) | = *= /= %= += -= | assignment / compound assignment(赋值/复合赋值) | Right-to-left |
?: | conditional operator (条件操作符) | |||
16 | Sequencing(排序) | , | comma separator(逗号分隔符) | Left-to-right |
当一个表达式有两个具有相同优先级的操作符时,Grouping决定哪个操作符先计算:从左到右还是从右到左。
将所有子语句括在括号中(即使是那些因为优先级而不必要的语句)可以提高代码的可读性。