C++笔记 --- 运算符


 

目录

运算符

sizeof与typedef

new与delete

操作符优先级

(本章节中例子都是用 VS2005 编译调试的)


 

 

运算符

[算术运算符][逻辑运算符][关系运算符][运算符][复合运算符][赋值运算符]

运算分类                                                           
1)算术运算符

包括:

﹢(加),    ‐(减),    *(乘),    ∕(除),    ﹪(求模),    ++i(自增),    --i(自减),    i++(自增),

i--(自减)

注意:

  • 两个整型相除还为整型,两个负值除法求商中舍去方向一般 ' 向零取整 '
  • 不同类型运算,统一成高精度后再运算

例子:

View Code
 1 int a = 5;
 2 int b = 3;
 3 int c = 0;
 4 
 5 c = a+b;   //此时 c 的值为 8
 6 c = a-b;     //此时 c 的值为 2
 7 c = a*b;    //此时 c 的值为 15
 8 c = a/b;     //此时 c 的值为 1
 9 c = a%b;   //此时 c 的 值为  2
10 c = a ++;   //此时 c 的 值为 5
11 c = a --;     //此时 c 的值为 6 
12 c = ++ a;   //此时 c 的值为 6
13 c = --  a;    //此时 c 的 值为 5

那么现在在对 i++,++i为例子(i--与--i同理)说明下他们的区别,由下面例子来说明

View Code
 1 int c = 0, a = 0, b = 0;
 2 
 3 c =  ++a; // 此时 c 为1
 4 c = a     ;  // 此时 c 为 1
 5 //由此可以看到 c = ++a 的执行顺序好像是先执行 a 变量的自增 ,然后在执行 c = a 这个操作
 6 //所以可以这么理解 ++a 表示的是,先把变量a自加,然后再执行++a所在的执行语句
 7 
 8 c = b++; // 此时 c 为0
 9 c = b;      // 此时 c 为1
10 //由此可以看到 c = ++b 的执行顺序好像是先执行执行 c = b 这个操作 ,然后在执行  b 变量的自增操作
11 //所以可以这么理解 ++b 表示的是,先执行++a所在的执行语句,然后再执行把变量 b 自加这个操作

但是还有一个问题,要是一个语句中有多个 i++ 或者 ++i 呢?是执行多次自加还是只执行一次自加呢?让我们看看一个例子

View Code
 1 // 例1
 2 #include <iostream>
 3 #include <cstdlib>
 4 
 5 using namespace std;
 6 
 7 void main()
 8 {
 9     int c = 0, a = 0, b = 0;
10 
11     cout<<"两次次使用 ++a"<<endl;
12     c =  (++a) + (++a); 
13     cout<<"the value of c is "<<c<<endl;
14     c = a + a;
15     cout<<"the value of c is "<<c<<endl<<endl;
16     
17     cout<<"两次次使用 b++"<<endl;
18     c = (b++) + (b++);
19     cout<<"the value of c is "<<c<<endl;
20     c = b + b;
21     cout<<"the value of c is "<<c<<endl<<endl;
22 
23     a = 0;//先重新初始化下 变量a
24     cout<<"a++ 与 ++a 的混合使用, a++在前"<<endl;
25     c =  (++a) + (a++); 
26     cout<<"the value of c is "<<c<<endl;
27     c = a + a;
28     cout<<"the value of c is "<<c<<endl<<endl;
29 
30     a = 0;//先重新初始化下 变量a
31     cout<<"a++ 与 ++a 的混合使用, a++在后"<<endl;
32     c = (a++) + (++a); 
33     cout<<"the value of c is "<<c<<endl;
34     c = a + a;
35     cout<<"the value of c is "<<c<<endl<<endl;
36 
37     a = 0;//先重新初始化下 变量a
38     cout<<"一个 a++ 与 两个 ++a 的混合使用"<<endl;
39     c = (a++) +(++a) + (++a); 
40     cout<<"the value of c is "<<c<<endl;
41     c = a + a + a;
42     cout<<"the value of c is "<<c<<endl<<endl;
43 
44     a = 0;//先重新初始化下 变量a
45     cout<<"两个 a++ 与 一个 ++a 的混合使用"<<endl;
46     c = (a++) + (a++) + (++a); 
47     cout<<"the value of c is "<<c<<endl;
48     c = a + a + a;
49     cout<<"the value of c is "<<c<<endl<<endl;
50 
51     system("pause");
52 }

输出结果:

 现在好像有点头绪了吧,让我们梳理下上面所说的内容:

    • ++i 的执行流程好像就是把 i 的自增这个动作放到了执行语句的首部去执行,然后 i 自增这个动作结束后在回来执行 ++i 所在的执行语句
    • i++ 的执行流程好像就是把 i 的自增这个动作放到了执行语句的尾部去执行,然后执行完 i++ 所在的执行语句后在回来执行 i 自增这个动作
    • 按上面所说的我们在看看上面多个 i++ 和 ++i 组合产生的效果,执行语句先执行语句中的 ++i 让 i 自增n次(n便是在执行语句中 ++i 的次数),然后在执行 i++ 和 ++i 所在的执行语句,然后在执行 i++ 让 i 自增n次(n便是在执行语句中 i++ 的次数)

 

2)逻辑运算符

包括:

&&(与),    ||(或),    !(非)

注意:

最终会以bool值形式返回出来

例子:

View Code
 1 // 例1
 2 #include <iostream>
 3 #include <cstdlib>
 4 
 5 using namespace std;
 6 
 7 void main()
 8 {
 9     bool a;
10     a = ( 5+10 == 15 ) && ( 5+10 == 5 );
11     cout<<"a = ( 5+10 == 15 ) && ( 5+10 == 5 ) ?   "<<a<<endl;
12     a = ( 5+10 == 15 ) || ( 5+10 == 5 );
13     cout<<"a = ( 5+10 == 15 ) || ( 5+10 == 5 ) ?   "<<a<<endl;
14 
15     a = 0;
16     a = !a;
17     cout<<"a=0  !a= ?   "<<a<<endl<<endl;
18 
19     system("pause");
20 }
21 
22 /*******************************************
23 输出结果:
24 a = ( 5+10 == 15 ) && ( 5+10 == 5 ) ?   0
25 a = ( 5+10 == 15 ) || ( 5+10 == 5 ) ?   1
26 a=0  !a= ?   1
27 
28 请按任意键继续. . .
29 ********************************************/

 

3)关系运算符

包括:

<(小于),    <=(不大于),    >(大于),    >=(不小于),    ==(等于),    !=(不等于)

注意:

最终会以bool值形式返回出来

例子:

View Code
1 bool a = 0;
2 a = 5>10;    //a = 0
3 a = 5<10;    //a = 1
4 a = 5>=10;  //a = 0
5 a = 5<=10;  //a = 1
6 a = 5==10;  //a = 0
7 a = 5!=10;  //a = 1

 

4)位运算符

包括:

~ (取反),    &(位与),    | (位或),    ^ (位异或) ,    <<(左移) ,    >>(右移)

注意:

  • 所有位运算的处理都是建立在数据的内容以2进制形式
  • 左移形式:number<<n,将操作数number左移n位,丢弃移出位,以0填充

例子:

View Code
 1 unsigned double b = 0xffffffff,c = 0x0000ffff;
 2 
 3 cout<<hex;//把输出改为十六进制
 4 
 5 cout<<"the value of b is "<<b<<endl;
 6 cout<<"the value of c is "<<c<<endl<<endl;
 7 
 8 cout<<"c & b  then  "<<(c&b)<<endl;
 9 cout<<"c | b  then  "<<(c|b)<<endl;
10 cout<<"c ^ b  then  "<<(c^b)<<endl;
11 cout<<"~c     then  "<<~c<<endl;
12 cout<<"c<<4   then  "<<(c<<4)<<endl;
13 cout<<"c>>4   then  "<<(c>>4)<<endl;

输出结果:

 

5)复合赋值运算符

包括:

+=(加x等于),    -=(减x等于),    *=(乘x等于),    %=(除x取模等于),    /=(除x等于),

>>=(向右移n位等于),    <<=(向右移n位等于),    &=(与x与位等于),    ^=(与x异或位等于),

|=(与x或位等于)

解释:

我们以 += 为例,其他的也都一样,那么我们来看下面这个例子

1 int a = 0;
2 a += 1;   //此时 a 的值为 1, 其实这个就等价于 a = a +1;
3 a += 5+9;   //此时 a 的值为 15 , 道理同上,只是现在的 = 号的右边换成了表达式而已,也就是等价于 a = a + (5+9)

 

6)赋值运算符

说明:

对对变量赋值,格式为 变量名 = 表达式 or 常量 or 变量 or 有返回值的函数调用;

例子:

View Code
 1 // 例1 ---
 2 int max(int a; int b)
 3 {
 4      return a>b?a:b;
 5 }
 6 void main() 
 7 {
 8      int a, b, c, d;
 9      a = 0xff8;  //用常量赋值给变量, 十六进制赋值, 十进制表示为 4008,所以 a 值为 4008 
10      b = a;        //用变量赋值给变量,所以 b 值为 a 值为 4008
11      c = a+b;    //用表达式赋值给变量,所以 c 值为 a 值加上 b 值为 8016
12      d = max(a,c);   //用函数返回值赋值给变量,所以 d 值为 8016
13 }
14  
15 // 例2 ---
16  unsigned char a;
17  a = 0xff8;   //在变量赋值时候,若左边的值大于变量的所能存放的容量时候,会截取后半段,舍弃超出存储界限的前半段,所以此时 a 为 0xf8

 

[返回目录]


 

sizeof与typedef

 

---sizeof---------------------------

用法:

  • sizeof(object变量名 / 常量)
  • sizeof (typename类型名 )

说明:

  • sizeof(object变量名 / 常量)括号可加可不加,此时变量名,常量被解析成相对应的类型,返回类型占得内存字节数
  • sizeof(typename类型名) 例如 sizeof(int)括号必须有,返回类型占得内存字节数

例子:

View Code
 1 // 例子 -- 
 2  void main()
 3  {
 4      int ia;
 5      short sa;
 6 
 7      cout<<"整型变量的占用内存空间为:  "<<sizeof(ia)<<" 字节"<<endl;
 8      cout<<"短整型变量的占用内存空间为:  "<<sizeof(short)<<" 字节"<<endl;
 9  }
10 /********************************
11 整型变量的占用内存空间为: 4
12 短整型变量的占用内存空间为:  2
13 ********************************/

 

---typedef--------------------------

用途:

定义类型的同义词 <不是简单的宏替换>

格式:

  • typedef 类型 自定义名;
    此时声明变量时候可有两种方法:(1)类型 变量名;(2)自定义名 变量名; 
  • typedef* 类型 自定义名;
    此时声明指针时候可有两种方法:(1)类型* 指针变量名;(2)自定义名 指针变量名; 
  • typedef 返回类型 (*自定义名)();
    此时声明函数指针的时候可有两种方法:(1)类型 (*函数指针名) ();(2)自定义名 函数指针名; 

陷阱:

  • typedef在语法上是一个存储类型的关键字(与auto一样)虽然它并不影响对象的存储性质,但不能与auto,static,register,extern,mutable连用
  • typedef定义了一个类型的新别名,比如typedef char*PSTR,然后 int mystrcmp(const RSTR)const在这里给予了char*整个const的属性,所以const RSTR在这里为char* const

目的:

  • 为了隐藏特定类型,强调使用类型的目的
  • 允许一个类型有多个别名,使类型使用时目的明确易懂,跃过平台无关类型的限制
  • 简化结构体名<例:typedef struct tagPOINT{int x,y} Point;Point p1>
  • 为复杂的声明定义一个简单的别名

--------------------------------------------------------------------------------------------------------------

例子:

1 typedef int heigh;  //以后就可以用 heigh 来定义 int 类型 变量
2 heigh i;  //等价于  int i

来看个更复杂的例子:

1 typedef int*(*pfuc)(intchar*); //以后可以用 pfuc 来定义函数指针
2 pfuc a;   //等价于函数指针定义 int*(*a)(int,char *) 

点这里查看变量定义

 

[返回目录]


 

new与delete

 

---new--------------------------

形式:

  • 结构 typename *point_name=new typename                          
    •  (解释:  typename *point_name为声明指针类型名,new typename声明分配空间类型)
  • 类 typename *point_name=new typename(构造函数参数表)         
    • (解释:typename *point_name声明指针类型名,new typename(构造函数参数表)声明分配空间类型)
  • 数组 typename *point_name=new typename[]                          
    • (解释:typename *point_name声明指针类型名,new typename[]声明分配空间类型) 

说明:

由于point_name为地址,new动态生成的结构体无名称,不能用*point_name . 成员名来访问成员,但由于()优先级高,所以可以用(*point_name).   成员名来访问或用point_name -> 成员名

例子:

用new开辟变量,数组,类的例子

View Code
 1 // 例1 -- 开辟变量
 2 int *a = new int(0);  //开辟变量并初始化变量为0,当然也可以开辟不初始的变量如: int *a = new int
 3 
 4 //例2 -- 开辟数组
 5 int *a = new int[5];  //开辟数组,数组长度为5
 6 
 7 //例3 -- 开辟类实例
 8 class A
 9 {
10     int a ;
11 };
12 void main ()
13 {
14    A* a = new A();  //如果有构造函数有参数在括号中传递参数,如果有默认构造函数(即无参数的构造函数)括号可加可不加
15 }

 用new开辟的类调用其成员函数或成员的例子

View Code
 1 class A
 2 {
 3 public:
 4     void show(){cout<<"hello!"}<<endl;
 5 };
 6 void main()
 7 {
 8     A* a = new A;
 9     a->show();
10     (*a).show();
11 }

 

---delete-------------------------

形式:

  • 变量 delete point_name
  • 数组 delete []point_name

例子:

View Code
 1 class A
 2 {
 3 public:
 4     void show(){cout<<"hello!"}<<endl;
 5 };
 6 void main()
 7 {
 8     int *a = new int(0);
 9     int *b = new int[5];
10     A* c = new A;
11 
12     delete a;  //释放指针 a 指向的用new开辟出的变量内存
13     delete[] b;   //释放指针 b 指向的用new开辟出来的数组的内存 
14     delete c;   //释放指针 c 指向的用new开辟出来的类的实例的内存
15 }

 

---new与delete使用说明----------

  • 用new生成的变量/结构体/[]point_name(数组)用delete来释放
  • delete释放的都是new指针指向的内存,而不会删掉指针本身
  • 用new或new val[]分配的内存由delete或delete[]val来释放
  • 对空指针应用delete是安全的
  • 不能用sizeof操作符来确定动态分配数组包含的字节数
  • new与delete必须互相兼容,new与delete,new[ ]与delete[ ]

 

[返回目录] 


 

C++操作符的优先级

 

 

操作符及其结合性

功能

用法

L
L
L

::
::
::

全局作用域 
类作用域 
名字空间作用域

::name
class::name
namespace::name

L
L
L
L
L

.
->
[]
()
()

成员选择 
成员选择 
下标 
函数调用 
类型构造 

object.member
pointer->member
variable[expr]
name(expr_list)
type(expr_list)

R
R
R
R
R

++
--
typeid
typeid
显示强制类型转换 

后自增操作 
后自减操作 
类型ID
运行时类型ID
类型转换 

lvalue++
lvalue--
typeid(type)
typeid(expr)
cast_name<type>(expr)

R
R
R
R
R
R
R
R
R
R
R
R
R
R

sizeof
sizeof
++
--
~
!
-
+
*
&
()
new
delete
delete[]

对象的大小 
类型的大小 
前自增操作 
前自减操作 
位求反 
逻辑非 
一元负号 
一元正号 
解引用 
取地址 
类型转换 
创建对象 
释放对象 
释放数组

sizeof expr
sizeof(type)
++lvalue
--lvalue
~expr
!expr
-expr
+expr
*expr
&expr
(type)expr
new type
delete expr
delete []expr

L
L

->*
.*

指向成员操作的指针 
指向成员操作的指针

ptr->*ptr_to_member
obj.*ptr_to_member

L
L
L

*
/
%

乘法 
除法 
求模(求余)

expr * expr
expr / expr
expr % expr

L
L

+
-

加法 
减法

expr + expr
expr - expr

L
L

<< 
>>

位左移 
位右移

expr << expr
expr >> expr

L
L
L
L


<=

>=

小于 
小于或等于 
大于 
大于或等于

expr < expr
expr <= expr
expr > expr
expr >= expr

L
R

==
!=

相等 
不等

Expr == expr
Expr != expr

R

&

位与

Expr & expr

R

^

位异或

Expr ^ expr

R

|

位或

Expr | expr

R

&&

逻辑与

Expr && expr

R

||

逻辑或

Expr || expr

R

?:

条件操作

Expr ? expr : expr

R
R
R
R
R

=
*=,/=,%=
+=,-=
<<=,>>=
&=,|=,^=

赋值操作 
符合赋值操作 

Lvalue= expr
Lvalue+= expr
…… 

R

throw

抛出异常

Throw expr

L

,

逗号

Expr, expr

前缀递增/递减与解除引用优先级相同;后缀递增/递减高于解除引用

 

[返回目录]

 

posted @ 2012-06-14 13:43  kzangv  阅读(1416)  评论(0编辑  收藏  举报
top